/**
 * clouds.js
 *
 * Copyright 2007 Andrew Sterling Hanenkamp.
 *
 * This program is free software. It may be redistributed under the terms of
 * the GNU General Public License. 
 *
 * If you find this code useful, I would like to hear about it. Please email me
 * at hanenkamp@cpan.org.
 */

function BlueSky(banner) {
    this.banner = jQuery(banner);
}

BlueSky.prototype = {
    banner: null,

    clouds: [],

    nextCloudIn: 0,

    addCloud: function(cloud) {
        cloud.sky = this;
        cloud.serial = this.clouds.length;
        this.clouds.push(cloud);
    },

    start: function() {
        this.loadClouds();
        var sky = this;
        setTimeout(function(){sky.animate()}, 1000);
    },

    shuffleClouds: function() {
        this.clouds = this.clouds.sort(function() { return Math.floor(Math.random() * 2) - 1});
    },

    getCloudBySerial: function(serial) {
        for (var i = 0; i < this.clouds.length; i++) {
            if (this.clouds[i].serial == serial) {
                return this.clouds[i];
            }
        }
        return null;
    },

    activateCloud: function(cloud, x, y) {
        cloud.reset(x, y);
        cloud.active = true;
        this.banner.append(cloud.img);
        this.nextCloudIn += cloud.img.width;
    },

    deactivateCloud: function(cloud) {
        jQuery(cloud.img).remove();
        cloud.active = false;
    },

    animate: function() {
        var lookForCloud = false;
        if (--this.nextCloudIn <= 0) {
            this.shuffleClouds();
            lookForCloud = true;
            this.nextCloudIn = Math.floor(Math.random() * (this.width() / 4));
        }

        for (var i = 0; i < this.clouds.length; i++) {
            var cloud = this.clouds[i];

            if (cloud.active) {
                cloud.nudge();

                if (cloud.isOffscreen()) {
                    this.deactivateCloud(cloud);
                }
            }

            else if (lookForCloud) {
                lookForCloud = false;
                this.activateCloud(cloud);
            }
        }

        this.saveClouds();

        var sky = this;
        setTimeout(function(){sky.animate()}, 1000);
    },

    width: function() {
        if (self.innerWidth) {
            return self.innerWidth;
        }
        else if (document.documentElement && document.documentElement.clientWidth) {
            return document.documentElement.clientWidth;
        }
        else if (document.body) {
            return document.body.clientWidth;
        }
        else {
            return 100;
        }
    },

    height: function() {
        if (this.banner.clientHeight) {
            return this.banner.clientHeight;
        }
        else {
            return 100;
        }
    },

    saveClouds: function() {
        var saveStr = "";
        for (var i = 0; i < this.clouds.length; i++) {
            var cloud = this.clouds[i];
            if (cloud.active) {
                saveStr += "(" + cloud.serial + "=" + cloud.x + ":" + cloud.y + ")";
                //console.log("[" + saveStr + "] Saving " + cloud.img.src + " at (" + cloud.x + ", " + cloud.y + ")");
            }
        }
        document.cookie = "CLOUDSTATE=" + saveStr + ";path=/";
    },

    loadClouds: function() {
        var cookies = document.cookie.split(/\s*;\s*/);
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i];
            if (/^CLOUDSTATE=/.test(cookie)) {
                var loadStr = cookie.substr(11);
                var cloudDigitGroups = cookie.substr(11).match(/(\d+=-?\d+:-?\d+)/g);
                if (!cloudDigitGroups) return; // quit if something went wrong
                for (var j = 0; j < cloudDigitGroups.length; j++) {
                    var cloudDigits = cloudDigitGroups[j];
                    var cloudDigitVals = cloudDigits.match(/-?\d+/g);

                    var serial = cloudDigitVals[0];
                    var x = cloudDigitVals[1];
                    var y = cloudDigitVals[2];

                    var cloud = this.getCloudBySerial(serial);
                    if (cloud != null) {
                        //console.log("[" + cloudDigits + "] Activating " + cloud.img.src + " at (" + x + ", " + y + ")");
                        this.activateCloud(cloud, x, y);
                    }
                }

                return;
            }
        }
    }
};

BlueSky.Cloud = function(src, title) {
    this.img = new Image();
    this.img.src = src;
    if (title) {
        this.img.alt = title;
    }
    else {
        this.img.alt = "A nice cloud floating across in the background.";
    }
    this.img.title = title;
    this.img.style.zIndex = 1;
    this.img.style.position = 'absolute';
    this.img.style.top = '0px';
    this.img.style.left = -this.img.width + 'px';
}

BlueSky.Cloud.prototype = {
    sky: null,

    img: null,

    x: 0,
    y: 0,

    active: false,

    serial: 0,

    title: null,

    nudge: function() {
        this.x++;
        this.img.style.left = this.x + 'px';
    },

    reset: function(x, y) {
        if (x != undefined) {
            this.x = x;
        }
        else {
            this.x = -this.img.width;
        }

        if (y != undefined) {
            this.y = y;
        }
        else {
            this.y = Math.floor(Math.random() * this.sky.height() - this.sky.height() / 2);
        }

        this.img.style.left = this.x + 'px';
        this.img.style.top  = this.y + 'px';
    },

    isOffscreen: function() {
        return this.isOffscreenLeft() || this.isOffscreenRight();
    },

    isOffscreenLeft: function() {
        return this.x < -this.img.width;
    },

    isOffscreenRight: function() {
        return this.x > this.sky.width();
    }
};
