var currentStrategy;

/**
 * Initializes the director.
 */
function initialize(doPlay){
    animUtil = new AnimationUtil();
    animUtil.init();
    animUtil.shuffle();
}

function AnimationUtil(){

    var messengerUpdateInterval = 60; // messenger fetching interval in seconds
    var FLASH_PLAYER_ID = "flashPlayer";
    var FLASH_CLIPS_ID = "o123";
    
    // state variables:
    var doShuffle = false;
    var doHover = false;
    var itemsReady = false;
    var itemsMoving = false;
    
    var meAnimUtil = this;
    var logo; // the logo image item
    var isLogoBubbleShown = false;
    
    var animator, updater, manager, intro, mutator;
    
    var items, inItems, outItems;
    var wd, center;
    var shuffleInterval;
    
    var actorIdPrefix = 'item';
    
    this.sndPlayer;
    
    this.init = function(){
    
        if (DEBUG) {
            console.debug("init of anim util");
        }
		
        //this.sndPlayer = initSounds();
        initWindowsDim();
        initItems();
        itemsReady = true;
        initDynElemManager();
        initAnimator();
        
        currentStrategy = StrategyBuilder.STRATEGY_NAMES[0];
        
        initStrategies();
        
        mutator = new StrategyMutator(animator);
        this.startLogoAnimation();
        this.showUIElements();
        this.showUIControls();
        
        this.runCurrentStrategyWithAllItems();
        
        this.makeItemsVisible();
        
    }
    
    this.isDevelopmentMode = function() {
        return configuration.DEBUG;
    }    
    
    this.getAllItems = function(){
        return items;
    }
    
    this.getAllOutItems = function(){
        return outItems;
    }
    
    this.getAllInItems = function(){
        return inItems;
    }
    
    this.getWindowDimensions = function(){
        return wd;
    }
    
    this.getCenter = function(){
        return center;
    }
    
    this.getAnimator = function(){
        return animator;
    }
    
    this.getLogo = function(){
        return logo;
    }
    
    this.isAnimating = function(){
        return (!doHover && itemsMoving);
    }
    
    this.startLogoAnimation = function(){
    
        logo = new ItemBuilder().newImageItem("logotype", "/images/logo_small.gif", 83, 69);
        logo.setPosition(new Point(-200, -200));
        
        logo.setStyle('cursor', 'pointer');
        //logo.addNeighbor("/images/online_bubble.gif", 30, -100, 145, 122);
        //logo.getNeighbor().setStyle('cursor', 'pointer');
        logo.setZindex(1000);
        
        var logoRotationCenter = new Point(wd.centerX, wd.centerY);
        var logoStrategy = new StrategyTwister(
          configuration.logoRotationSteps,
          logoRotationCenter, 
          configuration.logoRotationRadius, 
          5, RotationDirection.CCW);
        logoStrategy.addItem(logo);
        animator.registerStrategy("logoStrategy", logoStrategy);
        
        wd.addListener({
            logoStrategy: logoStrategy,
            windowChanged: function(winDims){
                logoRotationCenter.setPosition(new Point(winDims.centerX, winDims.centerY));
            },
            toString: function(){
                return "anonymous window dimensions listener - ";
            }
        });
        
        logoStrategy.resume();
        logo.show();
    }
    
    this.makeItemsVisible = function(){
    
        if (!itemsReady) {
            return;
        }
        
        for (var i = 0; i < items.length; i++) {
            items[i].show();
        }
    }
    
    this.runCurrentStrategyWithAllItems = function(){
        
        if (!itemsReady) {
            return;
        }
        
        meAnimUtil.runCurrentStrategyWithItems(items);
        doShuffle = true;
    }
    
    this.runCurrentStrategyWithItems = function(items){

        if (!itemsReady) {
            return;
        }
        currentStrategy.addItems(items);
        itemsMoving = true;
        disableEnableSliders(false);
    }
    
    this.doStandingHoverOnCircle = function(){
        if (!itemsReady) {
            return;
        }
        doShuffle = false;
        doHover = true;
        itemsMoving = false;
        var startPositionsRadius = startPosRadius;
        var standSteps = standingSteps;
        var fadingSteps = fadeToStandingAnimationSteps;
        
        var positions = new StrategyCircle(1, center, startPositionsRadius).getPositions(items.length);
        mutator.fadeItemsToStandingTwisters(items, positions, fadingSteps, standSteps);
        
        inItems = new Array();
        outItems = items.slice();
        
        disableEnableSliders(true);
    }
    
    this.outItemsBackToStrategy = function(){
        if (!itemsReady) {
            return;
        }
        mutator.fadeItemsToStrategy(outItems, currentStrategy, configuration.stepsToLineItemsUp);
        inItems = items.slice();
        outItems = new Array();
        doHover = false;
        itemsMoving = true;
        doShuffle = true;
        
        disableEnableSliders(false);
    }
    
    function disableEnableSliders(bool){
        if (radiusSlider && speedSlider) {
            if (bool) {
                radiusSlider.setDisabled(true);
                speedSlider.setDisabled(true);
            }
            else {
                radiusSlider.setEnabled(true);
                speedSlider.setEnabled(true);
            }
        }
    }
    
    this.lineAllItemsUp = function(){
        if (!itemsReady) {
            return;
        }
        
        doHover = false;
        itemsMoving = false;
        doShuffle = false;
        
        var bottomLeft = wd.getBottomLeftPoint();
        var bottomRight = wd.getBottomRightPoint();
        bottomLeft = bottomLeft.add(new Point(lineUpXOffset, -1 * lineUpYOffset));
        bottomRight = bottomRight.add(new Point(-1 * lineUpXOffset, -1 * lineUpYOffset));
        
        if (DEBUG) {
            console.debug("Lining up customizied @:\nbottom_left=" + bottomLeft.toString() + "\nbottomRight=" + bottomRight.toString());
        }
        
        mutator.lineUpItems(configuration.items, bottomLeft, bottomRight, configuration.stepsToLineItemsUp);
        outItems = items.slice();
        inItems = new Array();
        disableEnableSliders(true);
    }
    
    this.pauseCurrentStrategy = function(){
        currentStrategy.pause();
    };
    this.resumeCurrentStrategy = function(){
        currentStrategy.resume();
    };
    
    function initSounds(){
        var flashClipsId = FLASH_CLIPS_ID;
        var noOfClips = 5;
        var flashPlayId = FLASH_PLAYER_ID;
        
        var player = new SoundPlayer();
        player.setRandomSoundsMovie(flashClipsId, noOfClips);
        player.setFlashPlayer(flashPlayId);
        
        return player;
    }
    
    function initWindowsDim(){
    
        wd = new WindowDimensions(self);
        center = new ComplexPoint(wd.centerX, wd.centerY);
        center.windowChanged = function(windowDimensions){
            this.setPosition(new Point(wd.centerX, wd.centerY));
        }
        wd.addListener(center);
    }
    
    
    function _getImageItem(actorBean){
        var actorId = actorBean.id;
        var imagePath = configuration.ctx + "/actorDelivery!actor.action?id=" + actorId;
        
        // preload to be sure that actors get correct dimensions:
        if (!actorBean.width && !actorBean.height) {
            var img = new Image();
            img.src = imagePath;
            actorBean.width = img.width;
            actorBean.height = img.height;
        }
        
        var item = new ItemBuilder().newImageItem(actorIdPrefix + actorId, imagePath, actorBean.width, actorBean.height);
        
        item.hide();
        
        var hasBubble = (actorBean.bubbleId != null);
        if (hasBubble) {
            var bubbleSrc = configuration.ctx + "/bubbleDelivery!bubble.action?id=" + actorBean.bubbleId;
            item.addNeighbor(bubbleSrc, actorBean.bubbleX, actorBean.bubbleY, actorBean.bubbleWidth, actorBean.bubbleHeight);
        }
        
        var dayId = actorBean.dayId;
        if (dayId != null) {
            item.dayId = dayId;
        }
        
        return item;
    }
    
    
    this.generateMessengersByAjaxResponse = function(responseTxt, animator){
    
        var object = eval("(" + responseTxt + ")");
        var actorBean = object.actor;
        
        if (!actorBean) 
            return;
        
        var item = _getImageItem(actorBean);
        item.setZindex(configuration.MAX_ZINDEX - 2);
        if (item.hasNeighbor()) {
            item.neighbor.setZindex(configuration.MAX_ZINDEX - 1);
        }
        
        var points = object.strategy;
        var prePausePoints = new Array();
        var pause;
        var postPausePoints = new Array();
        var messengerSteps = object.steps;
        
        var dim = this.getWindowDimensions();
        
        var i;
        for (i = 0; i < points.length; i++) {
            if (!points[i].pause) {
                prePausePoints.push(dim.getPoint(points[i].x, points[i].y));
            }
            else {
                break;
            }
        }
        for (; i < points.length; i++) {
            if (points[i].pause) {
                var t = points[i].ms;
                pause = new StrategyPause(item, t / animator.getFrameMs(), function(itemHasNeighbor){
                    if (item.hasNeighbor()) {
                        item.showNeighbor();
                    }
                    //Effect.Pulsate(item.div, {duration: t / 1000});
                }, function(itemHasNeighbor){
                    if (item.hasNeighbor()) {
                        item.hideNeighbor();
                    }
                });
            }
            else {
                postPausePoints.push(dim.getPoint(points[i].x, points[i].y))
            }
        }
        
        var destroyer = new StrategyPause(item, 2, function(){
        }, function(){
            Element.remove($(item.div.id));
        });
        
        item.setPosition(prePausePoints.shift());
        item.show();
        
        var movement = new StrategyPolygon(item, prePausePoints.concat(pause).concat(postPausePoints).concat(destroyer), false, messengerSteps);
        
        animator.registerStrategyAutoUnregister(movement);
    }
    
    function initItems(){
    
        items = new Array();
        outItems = new Array();
        inItems = new Array();
        
        var initPosRadius = configuration.initPosRadius;
        var startPositions = new StrategyCircle(1, center, initPosRadius).getPositions(configuration.imageNames.length, 1);
        
        for (var i = 0; i < configuration.imageNames.length; i++) {
            var actorBean = configuration.imageNames[i];
            var item = _getImageItem(actorBean);
            
            item.setPosition(startPositions[i]);
            
            items[i] = item;
            item.setZindex(2);
            
            var dayId = actorBean.dayId;
            if (dayId != null) {
                item.setStyle("cursor", "pointer");
                item.addEvent("day", "onclick", function(){
                    var day = window.open("day.action?dayId=" + this.dayId, "day", "width=420,height=470,scrollbars=1");
                    day.focus();
                });
            }
            
            inItems.push(item);
        }
    }
    
    this.getCurrentStrategy = function(){
        return currentStrategy;
    }
    
    this.getDynElemManager = function(){
        return manager;
    }
    
    this.toggleAnimation = function(){
        if (animator.isRunning()) {
            this.stopAnimation();
        }
        else {
            this.resumeAnimation();
        }
    }
    
    this.stopAnimation = function(){
    
        if (!animator.isRunning()) {
            return;
        }
        
        animator.stop();
        clearInterval(shuffleInterval);
        shuffleInterval = null;
    }
    
    this.resumeAnimation = function(){
    
        if (animator.isRunning()) {
            return;
        }
        
        animator.start();
        this.shuffle();
    }
    
    function initDynElemManager(){
        //manager = new DynElemManager(self);
        //manager.newDynElem("archive_bubble", 214, 86, 10).moveTo(330, 23);
        //manager.newDynElem("online_bubble", 226, 125, 10).moveTo(185, 40);
    }
    
    function initAnimator(){
        animator = new Animator();
        animator.start();
    }
    
    function initStrategies(){

        var steps = configuration.steps;
        var radius = configuration.radius;
        var angSpeed = configuration.angSpeed;
                
        var strategyNames = StrategyBuilder.STRATEGY_NAMES;
        
        var builder = new StrategyBuilder();
        builder.setAngularSpeed(angSpeed);
        builder.setCenter(center);
        builder.setDirection(RotationDirection.CW);
        builder.setRadius(radius);
        builder.setSecondaryRadius(radius / 2);
        builder.setSteps(steps);
        
        builder.setSecondaryRadiusIncrement(-0.1);
        builder.setMainRadiusIncrement(0.4);
        builder.setSecondarySpeed(500);
        builder.setRadiusMin(10);
        builder.setRadiusMax(wd.getWidth() / 1.5);
                        
        for (var i = 0; i < strategyNames.length; i++) {

            var strategyName = strategyNames[i];
            var strategy = builder.createStrategy(strategyName);         
            animator.registerStrategy(strategyName, strategy);
            if (i == 0) {
                currentStrategy = strategy;
            }
        }
        
    }
    
    this.shuffle = function(){
    
        if (!itemsReady) {
            //alert("Items not ready");
            return;
        }
        
        var ms = configuration.shuffleIntervalMs;
        
        shuffleInterval = setInterval(function(){
            //shuffleLogoBubble(configuration.logoBubbleProb);
            if (doShuffle && itemsMoving && !doHover) {
                shuffleZIndex(configuration.zIndexChangeProb);
                randFlyIn(configuration.flyInProb);
                randFlyOut(configuration.flyOutProb);
                
                if(!randNewStrategy(configuration.newStrategyProb)) {
                    if(randChangeDirection(0.3)) {
                        revertLogoRotationDirection();
                    }
                }
                
            }
        }, ms);
        
        //alert("Leaving: shuffle, items moving: " + itemsMoving + ", shuffling: " + doShuffle);
    }
    
    function shuffleLogoBubble(probability){
    
        if (Math.random() > probability) {
            return;
        }
        if (isLogoBubbleShown) {
            logo.hideNeighbor();
            isLogoBubbleShown = false;
        }
        else {
            logo.showNeighbor();
            isLogoBubbleShown = true;
        }
    }
    
    function shuffleZIndex(probability){
    
        if (Math.random() > probability) {
            return;
        }
        
        for (var i = 0; i < inItems.length; i++) {
        
            var zIndex = Math.round(configuration.MAX_ZINDEX * Math.random());
            if (zIndex > configuration.MAX_ZINDEX) {
                zIndex = configuration.MAX_ZINDEX;
            }
            if (inItems[i]) {
                inItems[i].setZindex(zIndex);
            }
        }
    }
    
    function randFlyOut(probability){
        if (Math.random() > probability) {
            return;
        }
        var p = new Point(1000, 200);
        var item = getRandomIndex(inItems, true);
        if (item != null) {
            var toggle = Math.random() > 0.5;
            var randX = Math.random() * 500;
            var randY = Math.random() * 500;
            var x = toggle ? randX * -1 : randX + 1600;
            var y = toggle ? randY * -1 : randY + 1200;
            var velocity = Math.random() * 300 + 20;
            mutator.moveItemToPoint(item, new Point(x, y), velocity);
            outItems.push(item);
        }
        else {
            inItems.push(item);
        }
    }
    
    function randFlyIn(probability){
        if (Math.random() > probability) {
            return;
        }
        
        var item = getRandomIndex(outItems, true);
        if (item != null) {
            currentStrategy.addItem(item);
            inItems.push(item);
        }
        else {
            outItems.push(item);
        }
    }
    
    function randChangeDirection(probability){
               
        if (Math.random() > probability) {
            ///alert("Strategy change skipped");
            return false;
        }
        //alert("reverting direction");
        currentStrategy.revertRotationDirection();
        return true;
    }
    
    function revertLogoRotationDirection(){

        var candidate = logo.movementStrategy;
        
        if(candidate && candidate.revertRotationDirection) {
            // paranoid
            candidate.revertRotationDirection();
        }
    }    
    
    function randNewStrategy(probability){
        
        //alert("Entering strategy change");        
       
        if (Math.random() > probability) {
            ///alert("Strategy change skipped");
            return false;
        }
        
        var strategyNames = StrategyBuilder.STRATEGY_NAMES;
        var strategy;
        do {
            strategy = animator.getStrategyById(getRandomIndex(strategyNames, false));
        }
        while (strategy == currentStrategy);
        
        strategy.addItems(currentStrategy.removeAllItems());
        currentStrategy = strategy;
        return true;
    }
    
    function getRandomIndex(array, remove){
        var rand = Math.round((Math.random() * array.length) - 1);
        if (rand < 0) 
            rand = 0;
        if (!remove) {
            return array[rand];
        }
        else {
            return splicedOut = array.splice(rand, 1)[0];
        }
    }
    
    this.showInterface = function(timeline){
        timeline.addEvent(1, meAnimUtil.showUIElements);
        timeline.addEvent(showInterfaceMs, meAnimUtil.onIntroEnd);
    }
    
    this.showUIElements = function(){
        $("navigation").style.display = "block";
        $("vodilanew").style.display = "block";
        var stopStartButton = $("stop")
        stopStartButton.style.display = "block";
        stopStartButton.animUtil = this;
        var texts = document.getElementsByClassName("teaser");
        for (var i = 0; i < texts.length; i++) {
            var text = texts[i];
            text.style.display = "block";
        }
    }
    
    this.hideSliders = function(){
        $("vodilanew").style.display = "none";
    }
    
    this.showSliders = function(){
        $("vodilanew").style.display = "block";
    }
    
    this.showUIControls = function(){
        createRadiusSlider();
        createLogoRadiusSlider();
        createStepsSlider();
    }
    
    this.onIntroEnd = function(){
        meAnimUtil.showUIControls();
        intro.onIntroEnd();
    }
    
    function createLogoRadiusSlider(){
    
        logoSlider = new Control.Slider('handle_track_3', 'vodila_track_3', {
            range: $R(10, 800)
        });
        
        var text = $('logo_radius_text');
        logoSlider.setDisabled();
        
        var catcher = logo.movementStrategy;
        catcher.setCatchListener(function(followee, item, strategy){
            
            logoSlider.currentStrategy = strategy;
            logoSlider.setValue(logoSlider.currentStrategy.getRadius());
            logoSlider.setEnabled();
            //alert("Login catched");
            
         });
        //alert(logoSlider.currentStrategy);
        //logoSlider.setValue(logoSlider.currentStrategy.getRadius());
        
        logoSlider.options.onSlide = function(value){
            var rad = value.toFixed();
            text.innerHTML = rad;
            logoSlider.currentStrategy.setRadius(rad);
        };
        
        logoSlider.setText = function(value){
            text.innerHTML = value;
        }
        
        logoSlider.setText(configuration.logoRotationRadius);
    }
    
    var radiusSlider, speedSlider;
    
    function createRadiusSlider(){
    
        radiusSlider = new Control.Slider('handle_track_2', 'vodila_track_2', {
            range: $R(0, wd.centerX)
        });
        
        radiusSlider.setValue(configuration.radius);
        var text = $('radius_text');
        
        radiusSlider.options.onSlide = function(value){
            var r = value.toFixed();
            setRadius(r, meAnimUtil);
            text.innerHTML = r;
            currentStrategy.setRadius(r);
        };
        
        radiusSlider.setDisabled(true);
        
        radiusSlider.setText = function(value){
            text.innerHTML = value;
        }
        
        radiusSlider.setText(configuration.radius);
    }
    
    function createStepsSlider(){
    
        speedSlider = new Control.Slider('handle_track_1', 'vodila_track_1', {
            range: $R(10, 700)
        });
        
        speedSlider.setValue(configuration.steps);
        var text = $('velo_text');
        
        speedSlider.options.onSlide = function(value){
            var s = value.toFixed();
            setSteps(s, meAnimUtil);
            text.innerHTML = s;
        };
        
        speedSlider.setDisabled(true);
        
        speedSlider.setText = function(value){
            text.innerHTML = value;
        }
        
        speedSlider.setText(configuration.steps);
    }
    
}

// sliders:
var logoSlider, volumeSlider, playerSlider;


function setRadius(newRadius, animationUtil){
    configuration.radius = Math.round(newRadius);
    var strategies = StrategyBuilder.STRATEGY_NAMES;
    var animator = animationUtil.getAnimator();
    for (var i = 0; i < strategies.length; i++) {
        var strat = animator.getStrategyById(strategies[i]);
        if (strat != animationUtil.getCurrentStrategy()) {
            strat.setRadius(configuration.radius);
        }
    }
    
}

function setSteps(newSteps, animationUtil){
    configuration.steps = Math.round(newSteps);
    var strategies = StrategyBuilder.STRATEGY_NAMES;
    var animator = animationUtil.getAnimator();
    for (var i = 0; i < strategies.length; i++) {
        var strat = animator.getStrategyById(strategies[i]);
        strat.setSteps(configuration.steps);
    }
}

function showPlayerControls(){

    if (volumeSlider == null || playerSlider == null) {
        showPlayer();
        showVolume();
    }
    
    playerSlider.setValue(34);
}


function notifyStreamReload(message){
    if (top) {
        top.status = message;
    }
}

