/**
 * Initializes animation.
 */
function AnimationUtil(configuration) {

    // state variables:
    this.doShuffle = true;
    this.itemsReady = false;
    this.itemsMoving = false;
    
    var logo; // the logo image item
    var isLogoBubbleShown = false;
    
    var animator, mutator;
    
    var items, inItems, outItems;
    var wd, center;
    var shuffleInterval;
    
    var actorIdPrefix = 'item';
    
    this.configuration = $H(configuration);
    
    this.configuration.each(function(pair) {
        this[pair.key] = pair.value;
    }.bind(this));
    
    this.init = function(animateLogo) {
    
        initWindowsDim();
        
        this.initItems();
        initAnimator();
        
        this.itemsReady = true;
        this.initStrategies();
        
        mutator = new StrategyMutator(animator);
        this.makeItemsVisible();
        
        this.runCurrentStrategyWithAllItems();
        this.itemsMoving = true;
        
        if (animateLogo) {
            this.startLogoAnimation();
        }
        
        if (this.doShuffle) {
            this.shuffle();
        }
    }
    
    this.toString = function() {
    
        var result = ""
        
        this.configuration.each(function(pair) {
            this[pair.key] = pair.value;
            result += pair.key + " = " + pair.value + "\n";
        });
        
        return result;
    }
    
    this.isDevelopmentMode = function() {
        return this.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.getMutator = function() {
        return mutator;
    }
    
    this.setConfiguration = function(configuration) {
    
        var configuration = $H(configuration);
        
        configuration.each(function(pair) {
            this[pair.key] = pair.value;
        });
    }
    
    this.initItems = function() {
    
        items = new Array();
        outItems = new Array();
        inItems = new Array();
        
        var startPositions = new StrategyCircle(1, center, this.initPosRadius).getPositions(this.imageNames.length);
        
        for (var i = 0; i < this.imageNames.length; i++) {
            var actorBean = this.imageNames[i];
            var item = getImageItem(actorBean);
            
            item.setPosition(startPositions[i]);
            
            items[i] = item;
            item.setZindex(2);
            inItems.push(item);
        }
    }
    
    this.stop = function() {
        animator.stop();
    }
    
    this.startLogoAnimation = function() {
    
        logo = new ItemBuilder().newImageItem("logotype", "/images/logo_small.gif", 83, 69);
        
        logo.setPosition(new Point(-200, -200));
        
        //imageURL, xOffsetToMe, yOffsetToMe, width, height
        logo.addNeighbor("/images/online_bubble.gif", 0, -140, 151, 146);
        logo.setLink("/4duk/playerPage.action?play=true");
        var bubbel = logo.getNeighbor();
        bubbel.setLink("/4duk/playerPage.action?play=true");
        bubbel.setStyle('cursor', 'pointer');
        
        logo.setStyle('cursor', 'pointer');
        logo.setZindex(1000);
        bubbel.setZindex(1);
        
        var logoRotationCenter = new Point(wd.centerX, wd.centerY);
        
        //var logoStrategy = new StrategyTwister(this.logoRotationSteps, logoRotationCenter, this.logoRotationRadius, 5);
        var direction = RotationDirection.CCW;
        //alert(direction);
        var logoStrategy = new StrategyCircle(this.logoRotationSteps, logoRotationCenter, this.logoRotationRadius, direction);
        
        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 - ";
            }
        });
        
        logo.show();
        logo.getNeighbor().show();
        logoStrategy.resume();
    }
    
    this.makeItemsVisible = function() {
    
        if (!this.itemsReady) {
            return;
        }
        
        for (var i = 0; i < items.length; i++) {
            items[i].show();
        }
    }
    
    this.runCurrentStrategyWithAllItems = function() {
    
        if (!this.itemsReady) {
            return;
        }
        
        this.runCurrentStrategyWithItems(items);
    }
    
    this.runCurrentStrategyWithItems = function(items) {
    
        if (!this.itemsReady) {
            return;
        }
        
        this.currentStrategy.addItems(items);
        this.itemsMoving = true;
    }
    
    this.outItemsBackToStrategy = function() {
    
        if (!this.itemsReady) {
            return;
        }
        
        this.currentStrategy.addItems(outItems);
        inItems = items.slice();
        outItems = new Array();
        this.itemsMoving = true;
        this.doShuffle = true;
    }
    
    this.pauseCurrentStrategy = function() {
        this.currentStrategy.pause();
    };
    this.resumeCurrentStrategy = function() {
        this.currentStrategy.resume();
    };
    
    function initWindowsDim() {
    
        wd = new WindowDimensions(self);
        center = new ComplexPoint(wd.centerX, wd.centerY);
        center.windowChanged = function(windowDimensions) {
            this.setPosition(new Point(windowDimensions.centerX, windowDimensions.centerY));
        }
        wd.addListener(center);
    }
    
    function getImageItem(actorBean) {
    
        var actorId = actorBean.id;
        var imagePath = "/4duk/actorpic" + actorId + ".gif";
        var item = new ItemBuilder().newImageItem(actorIdPrefix + actorId, imagePath, actorBean.width, actorBean.height);
        
        //item.hide();
        
        return item;
    }
    
    this.getCurrentStrategy = function() {
        return this.currentStrategy;
    }
    
    this.toggle = function() {
        if (animator.isRunning()) {
            animator.start();
        }
        else {
            animator.stop();
        }
    }
    
    function initAnimator() {
        animator = new Animator();
        animator.start();
    }
    
    this.initStrategies = function() {
    
        var strategyNames = StrategyBuilder.STRATEGY_NAMES;
        var builder = new StrategyBuilder();
        builder.setAngularSpeed(this.angSpeed);
        builder.setCenter(center);
        builder.setDirection(RotationDirection.CW);
        builder.setRadius(this.radius);
        builder.setSecondaryRadius(this.radius);
        builder.setSteps(this.steps);
        
        builder.setSecondaryRadiusIncrement(-0.1);
        builder.setMainRadiusIncrement(0.23);
        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);
        }
        
        this.currentStrategy = animator.getStrategyById(this.startupAnimationStrategy);
    }
    
    this.shuffle = function() {
    
        if (!this.itemsReady) {
            return;
        }
        
        shuffleInterval = setInterval(function() {
            // shuffleLogoBubble(logoBubbleProb);
            
            //alert("shuffle: " + this.shuffleIntervalMs);
            
            if (this.doShuffle && this.itemsMoving) {
                this.shuffleZIndex(this.zIndexChangeProb);
                this.randFlyIn(this.flyInProb);
                randFlyOut(this.flyOutProb);
                this.randNewStrategy(this.newStrategyProb);
            }
        }
.bind(this), this.shuffleIntervalMs);
    }
    
    this.randFlyIn = function(probability) {
    
        if (Math.random() > probability) {
            return;
        }
        
        var item = getRandomIndex(outItems, true);
        if (item != null) {
            this.currentStrategy.addItem(item);
            inItems.push(item);
        }
        else {
            outItems.push(item);
        }
    }
    
    function randFlyOut(probability) {
    
        if (Math.random() > probability) {
            return;
        }
        
        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 steps = Math.random() * 300 + 20;
            var line = new StrategyLine(item, item.getPosition(), new Point(x, y), steps);
            animator.registerStrategyAutoUnregister(line);
            outItems.push(item);
        }
        else {
            inItems.push(item);
        }
    }
    
    this.randNewStrategy = function(probability) {
    
        if (Math.random() > probability) {
            return;
        }
        
        var strategyNames = StrategyBuilder.STRATEGY_NAMES;
        
        var strategy;
        do {
            strategy = animator.getStrategyById(getRandomIndex(strategyNames, false));
        }
        while (strategy == this.currentStrategy);
        
        strategy.addItems(this.currentStrategy.removeAllItems());
        this.currentStrategy = strategy;
        
        //alert("New strategy: " + strategy);
    }
    
    this.shuffleZIndex = function(probability) {
    
        if (Math.random() > probability) {
            return;
        }
        
        for (var i = 0; i < inItems.length; i++) {
        
            var zIndex = Math.round(this.MAX_ZINDEX * Math.random());
            
            if (zIndex > this.MAX_ZINDEX) {
                zIndex = this.MAX_ZINDEX;
            }
            
            if (inItems[i]) {
            
                inItems[i].setZindex(zIndex);
            }
        }
    }
    
    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];
        }
    }
}



