var STRATEGY_NAMES = ["StrategyCircle", "StrategyRotationY", "StrategyTwister", "StrategyRotationX", "StrategyHorizontalHop", "StrategyVerticalHop"];
var currentStrategy;

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

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 = STRATEGY_NAMES[0];

        initStrategies();

        mutator = new StrategyMutator(animator);
        this.startLogoAnimation();
        this.showUIElements();
        this.showUIControls();

        this.runCurrentStrategyWithAllItems();

        this.makeItemsVisible();

    }

    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);
        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);
    }

    this.runCurrentStrategyWithItems = function(items){
        if(!itemsReady){ return; }
        mutator.fadeItemsToStrategy(items, currentStrategy, configuration.fadeToNextStrategySteps);
        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).getFuturePoints(items.length, 1);
        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).getFuturePoints(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 = STRATEGY_NAMES;

      for(var i = 0; i < strategyNames.length; i++){
        var name = strategyNames[i];
        var strategy = eval("new " + name + "(steps, center, radius, angSpeed)");
        animator.registerStrategy(name, strategy);
        if(i == 0) {
          currentStrategy = strategy;
        }
      }

    }

    this.shuffle = function(){

        if(!itemsReady){
            return;
        }

        var ms = configuration.shuffleIntervalMs;

        shuffleInterval = setInterval(function() {
            shuffleLogoBubble(configuration.logoBubbleProb);
            if(doShuffle && itemsMoving && !doHover){
                shuffleZIndex(configuration.zIndexChangeProb);
                randFlyIn(configuration.flyInProb);
                randFlyOut(configuration.flyOutProb);
                randNewStrategy(configuration.newStrategyProb);
            }
        }, ms);
    }

    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){
            var velocity = Math.random() * 300 + 20;
            mutator.fadeItemToStrategy(item, currentStrategy, velocity);
            inItems.push(item);
        } else {
            outItems.push(item);
        }
    }

    function randNewStrategy(probability){
        var strategyNames = STRATEGY_NAMES;
        if(Math.random() > probability){ return; }
        var strategy;
        do{
            strategy = animator.getStrategyById(getRandomIndex(strategyNames, false));
        } while (strategy == currentStrategy);

        //strategy.setSteps(steps);
        mutator.fadeStrategyToNewStrategy(currentStrategy, strategy, configuration.fadeToNextStrategySteps);
        currentStrategy = strategy;
    }

    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.currentStrategy = logo.movementStrategy;
            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 = 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 = 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;
  }
}