/*************************************************************/
/*                          Globals                          */
/*************************************************************/

var cssClassHandle = 'anyTextHandle';

var MIN_ZINDEX_FOR_BOXES = 900;
var MIN_RADIUS = 227;

/*************************************************************/
/*                        Positioner                         */
/*************************************************************/

var CirclePositioner = Class.create();

CirclePositioner.prototype = {

    initialize: function() {
    
        },
    
    MIN_RADIUS: 227,
    
    position: function(layout, wd) {
    
        var textsRadius = (wd.height / 2) + configuration.textRadiusAdjustment;
        
        if (textsRadius < MIN_RADIUS) {
            textsRadius = MIN_RADIUS;
        }
        
        var amountSpacerPositions = 5;
        
        var amountTexts = layout.items.length;
        //var adjustmentTop = wd.getCenterPoint().getY() * configuration.textCenterOffsetTop;
        //var adjustmentLeft = wd.getCenterPoint().getX() * configuration.textCenterOffsetTop;
        var winCenter = wd.getCenterPoint().newPoint(configuration.textCenterOffsetLeft, configuration.textCenterOffsetTop);
        
        if (winCenter.getY() < textsRadius + 30) {
            winCenter.setY(textsRadius + 30);
        }
        
        //alert("text radius : " + textsRadius + ", offset top: " + configuration.textCenterOffsetTop);
        layout.positions = [];
        
        var anyTextPositions = this.getCircleCoords(amountTexts + amountSpacerPositions, textsRadius, winCenter);
        var split = (amountTexts / 2) - (amountSpacerPositions / 2) + 4;
        
        for (var i = 0; i <= split; i++) {
            layout.positions.push(anyTextPositions[i]);
        }
        
        i += amountSpacerPositions;
        
        for (; i < anyTextPositions.length; i++) {
            layout.positions.push(anyTextPositions[i]);
        }
        
    },
    
    getCircleCoords: function(amountItems, radius, centerP) {
    
        var steps = 90;
        var frame = 55;
        
        var pos = new Array();
        var itemCount = amountItems;
        
        var step = (steps / itemCount);
        var pi2Steps = 2 * Math.PI / steps;
        
        
        for (var i = 1; i <= itemCount; i++) {
        
            var tmp = (i * step + frame) * pi2Steps;
            
            var x = radius * Math.cos(tmp);
            var y = radius * Math.sin(tmp);
            
            pos.push(centerP.newPoint(x, y));
        }
        return pos;
    }
    
}

var QuietPositioner = Class.create();

QuietPositioner.prototype = {

    initialize: function() {
    
        },
    
    position: function(layout, wd) {
        layout.positions = [];
        
        for (var i = 0; i < layout.items.length; i++) {
            var item = layout.items[i];
            var css = item.getCss();
            var x = parseInt(css.left) - item.xOffset;
            var y = parseInt(css.top) - item.yOffset;
            layout.positions.push(new Point(x, y));
        }
        
    }
    
}

/*************************************************************/
/*                 ItemCreationStrategy                      */
/*************************************************************/

var TextItemCreationStrategy = Class.create();

TextItemCreationStrategy.prototype = {

    initialize: function() {
        },
    
    newItem: function(htmlElement) {
    
        return new ItemBuilder().newItem(htmlElement);
    }
    
}

var ImageItemCreationStrategy = Class.create();

ImageItemCreationStrategy.prototype = {

    initialize: function() {
        },
    
    newItem: function(htmlElement) {
    
        return new ItemBuilder().newImageItem(htmlElement.id, htmlElement.src, htmlElement.style.width, htmlElement.style.height);
    }
    
}

/*************************************************************/
/*                   AnyTextLayout                           */
/*************************************************************/

var AnyTextLayout = Class.create();

AnyTextLayout.prototype = {

    initialize: function(parentElement, creationStrategy, positioner, findBy) {
    
        this.parent = $(parentElement);
        this.creationStrategy = creationStrategy || new TextItemCreationStrategy(); // hack for a downward compatibility
        this.positioner = positioner || new CirclePositioner(); // hack for a downward compatibility
        this.findBy = findBy || "a.AnyTextClass"; // hack for a downward compatibility
        this.items = [];
        this.animatedItems = [];
        this.maxWidth = 0;
    },
    
    add: function(html) {
    
        new Insertion.Bottom(this.parent, new String(html));
        var newElem = $$(this.findBy).last();
        
        var asItem = new ItemBuilder().newItem(newElem);
        asItem.setZindex(MIN_ZINDEX_FOR_BOXES + 1);
        
        this.items[this.items.length] = asItem;
    },
    
    addElement: function(htmlElement) {
    
        if (htmlElement == null) {
            throw new Error("Element must not be null");
        }
        
        var asItem = this.creationStrategy.newItem(htmlElement);
        asItem.setZindex(MIN_ZINDEX_FOR_BOXES + 1);
        
        this.items[this.items.length] = asItem;
    },
    
    addElementById: function(id) {
    
        if (id == null) {
            throw new Error("Element id must not be null nor empty");
        }
        
        addElement($(id));
    },
    
    toString: function() {
        return "Elements: " + this.items.join(", ");
    },
    
    setPositions: function(wd) {
    
        this.positioner.position(this, wd);
        this.setItemPositions();
        
    },
    
    setItemPositions: function() {
    
        for (var index = 0; index < this.items.length; index++) {
            this.items[index].setPosition(this.positions[index]);
        }
        
    },
    
    showAll: function() {
    
        for (var index = 0; index < this.items.length; index++) {
        
            var item = this.items[index];
            item.show();
            
            var width = item.element.getDimensions()['width'];
            if (width > this.maxWidth) {
                this.maxWidth = width;
            }
        }
    },
    
    windowChanged: function(windowDimensions) {
        this.setPositions(windowDimensions);
    },
    
    getItems: function() {
        return this.items;
    },
    
    startJoinAnim: function(animUtils) {
    
        var ms = 1000;
        var boxJoinAnimProbability = configuration.boxJoinAnimProbability // very improbable 0.02;
        var boxLeaveAnimProbability = configuration.boxJoinAnimProbability;
        
        this.animUtils = animUtils;
        
        shuffleInterval = setInterval(function() {
        
            var velocity = Math.random() * 700 + 20;
            var didJustMoveOut = false;
            
            if (Math.random() < boxJoinAnimProbability) {
            
                var rndIndex = Math.round((Math.random() * this.items.length) - 1);
                if (rndIndex < 0) 
                    rand = 0;
                
                var itemGetsAnimated = this.items[rndIndex];
                if (itemGetsAnimated) {
                    this.animatedItems.push(itemGetsAnimated);
                    this.animUtils.getCurrentStrategy().addItem(itemGetsAnimated);
                    //alert("Added " + itemGetsAnimated);
                    didJustMoveOut = true;
                }
            }
            
            if (Math.random() < boxLeaveAnimProbability && this.animatedItems.length > 0 && !didJustMoveOut) {
                var rndIndex = Math.round((Math.random() * this.animatedItems.length) - 1);
                if (rndIndex < 0) 
                    rand = 0;
                
                var itemThatComesBack = this.animatedItems.splice(rndIndex, 1)[0];
                if (itemThatComesBack) {
                    var itemsPosition = this.positions[this.items.indexOf(itemThatComesBack)];
                    this.animUtils.getMutator().moveItemToPoint(itemThatComesBack, itemsPosition, velocity);
                }
            }
            
        }
.bind(this), ms);
    }
}

