// init mozz
var mozz = {};

mozz.honey = new Class (
{
    init: function(element)
    {
        // init temp vars
        var unique = new util.unique();
        
        // init vars
        this.current = 0;
        this.element = element;
        this.size = false;
        this.uid = unique.createUniqueObject(document);
    },
    
    setChange: function(options)
    {
        // init defaults
        this.type = 'size';
        this.orientation = 'height';
        this.direction = 'out';
        this.max = '100';
        this.min = '0';
        this.fps = 150;
        this.diff = 5;
        this.currentFrame = 0;
        
        // store the options
        this.storeOptions(options, true);
        
        // init vars
        document[this.uid] = this;
        var func = 'document.' + this.uid + '.change' + this.type.capitalise() + '()'
        this.isOut = this.direction == 'out' ? true : false;
        this.totalFib = ((this.fibonacci((Math.ceil(this.frames / 2)) + 2) - 1) * 2) - ((this.frames / 2) % 1 != 0 ? this.fibonacci(Math.ceil(this.frames / 2)) : 0);
        
        // clear any intervals
        if (this.interval) clearInterval(this.interval);
        
        // create the interval ready
        this.interval = setInterval(func, (1000 / this.fps));
    },
    
    changeSize: function()
    {
        // calc the new diff if needed
        if (this.frames) this.diff = this.getFibChange(++this.currentFrame, 1);
        
        // calc new size
        this.size = this.size == false ? this.element['client' + this.orientation.capitalise()] : this.size;
        var newSize = this.isOut ? (this.size + this.diff > this.max ? this.max : this.size + this.diff) : (this.size - this.diff < this.min ? this.min : this.size + this.diff);
        
        // change the size
        this.element.style[this.orientation] = newSize + 'px';
        this.size = newSize;
        
        // clear the interval when needed
        if ((this.size >= this.max && this.isOut) || (this.size <= this.min && !this.isOut) || (this.frames < this.currentFrame)) 
        {
            clearInterval(this.interval);
            this.size = false;
        }
    },
    
    changeFade: function()
    {
        // calc the new diff if needed
        if (this.frames) this.diff = this.getFibChange(++this.currentFrame, 1);
        
        // calc the new fade
        var current = typeof(this.element.style.opacity) == 'undefined' || this.element.style.opacity == '' ? (this.isOut ? 0 : 100) : (this.element.style.opacity * 100);
        var newFade = this.isOut ? (current + this.diff > this.max ? this.max : current + this.diff) : (current - this.diff < this.min ? this.min : current + this.diff);
        
        // sets the fade
        this.setOpacity(this.element, newFade > 0 ? newFade / 100 : 0);
        
        // check for appearing / disapparing (0.2 to catch rounding errors)
        if (((current <= 0.2 || newFade <= 0.2) && current != newFade))
            this.element.style.display = newFade <= 0.2 ? 'none' : 'block';
        
        // clear the interval when needed
        if ((newFade >= this.max && this.isOut) || (newFade <= this.min && !this.isOut) || this.currentFrame > this.frames)
        {
            if (this.remove && this.direction == 'in') this.element.style.display = 'none';
            clearInterval(this.interval);
        }
    },
    
    changeMove: function()
    {
        // calc the new diff if needed
        if (this.frames) this.diff = this.getFibChange(++this.currentFrame, 0);
        
        this.element.style.marginTop = (parseInt(this.element.style.marginTop) + this.diff) + 'px';
        
        // calc the new location
        if (this.currentFrame > this.frames)
            clearInterval(this.interval);
    },
    
    changeColour: function()
    {
        // get the colours
        var temp = new Array('', '', '');
        var diff = new Array(this.diff, this.diff, this.diff);
        var cols = new Array('r', 'g', 'b');
        var min = this.getDecimalColour(!this.isOut || (this.isOut && this.currentFrame == 0) ? this.min.toUpperCase() : this.element.style.backgroundColor.toUpperCase());
        var max = this.getDecimalColour(this.isOut || (!this.isOut && this.currentFrame == 0) ? this.max.toUpperCase() : this.element.style.backgroundColor.toUpperCase());
        this.currentFrame ++;
        
        // get the new values for the colour
        for (var i = 0; i < 3; i ++)
        {
            // get the new colour
            temp[i] = (this.isOut ? min[cols[i]] : max[cols[i]]) + ((min[cols[i]] <= max[cols[i]] ? 1 : -1) * (this.isOut ? 1 : -1) * this.diff);
            
            // check to see if we can keep it
            temp[i] = this.isOut  && ((max[cols[i]] >= min[cols[i]] && temp[i] >= max[cols[i]]) || (max[cols[i]] <= min[cols[i]] && temp[i] <= max[cols[i]])) ? max[cols[i]] : temp[i];
            temp[i] = !this.isOut && ((max[cols[i]] >= min[cols[i]] && temp[i] <= min[cols[i]]) || (max[cols[i]] <= min[cols[i]] && temp[i] >= min[cols[i]])) ? min[cols[i]] : temp[i];
        }
        
        // create the new colour
        var newCol = this.getHexColour({r: temp[0], g: temp[1], b: temp[2]});
        
        // change the colours
        if (this.useChildren == true)
        {
            // get the children
            var childs = this.element.parentNode.childNodes;
            
            // change the colours on the children
            for (var i = 0; i < childs.length; i ++)
                childs[i].style.backgroundColor = newCol;
        }
        else
            this.element.style.backgroundColor = newCol;
        
        // end the change if hit boundary
        if (min.r == max.r && min.g == max.g && min.b == max.b)
            clearInterval(this.interval);
    },
    
    fibonacci: function(position)
    {
        return Math.round(Math.pow((1 + Math.sqrt(5)) / 2, position) / Math.sqrt(5));
    },
    
    getFibChange: function(current, diff)
    {
        // init vars
        var midPoint = Math.ceil(this.frames / 2); 
        diff = typeof(diff) == 'undefined' ? 0 : diff;
        
        // check what current should be
        var current = midPoint < current ? this.frames - (current - ((this.frames / 2) % 1 == 0 ? 0 + diff : 1 + diff)) : current;
        
        // return the correct value
        return ((this.fibonacci(current) / this.totalFib) * Math.abs(this.max - this.min)) * (this.isOut ? 1 : -1);
    },
    
    // sets the opacity
    setOpacity: function(element, opacity)
    {
        // sets the opacity for IE
        if (document.all) element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
        
        // set the opacity for other browsers
        element.style.MozOpacity = opacity;
        element.style.opacity    = opacity;
    }, 
    
    // gets the decimal colours
    getDecimalColour: function(colour)
    {
        // check for rgb colour
        if (colour.substr(0, 3) == 'RGB')
        {
            // remove all the crap from the colour
            colour = colour.replace(/[^0-9,]/g, '');
            colour = colour.split(',');
            
            // return the new colour
            return {r: parseInt(colour[0]), g: parseInt(colour[1]), b: parseInt(colour[2])};
        }
        else
        {
            // remove all bad chars
            colour = colour.replace(/[^0-9A-F]/g, '');
            
            // return the new colour
            return {r: parseInt(colour.substr(0, 2), 16), g: parseInt(colour.substr(2, 2), 16), b: parseInt(colour.substr(4, 2), 16)};
        }
    },
    
    // translates a decimal colour to hex
    getHexColour: function(colour)
    {
        return '#' + (colour.r < 16 ? '0' : '') + colour.r.toString(16) + (colour.g < 16 ? '0' : '') + colour.g.toString(16) + (colour.b < 16 ? '0' : '') + colour.b.toString(16);
    }
});