var Lemmings = new Class({
    Implements: [Options, Events],
    lemmings: [],
    fireworks: [],
    options: {
        spriteWidth: 32,
        spriteHeight: 32,
        spriteContainerWidth: 256,
        spriteExplodeContainerWidth: 512,
        drawSpeed: 50,
        marginTop: 52,
        spriteZindex: 1000,
        daytime: "auto",
        daylightDetect: true,
        parallaxLayerSize: "100%"
    },
    parallax: {},
    setTheme: function() {
        this.container.setStyles({
            overflow: "hidden",
            background: "url(http://fragged.org/images/parallax-bottom"+this.theme+".gif)"
        });


        this.parallax.topLayer.setStyles({
            background: "url(http://fragged.org/images/parallax-top"+this.theme+".gif) no-repeat -400px top"
        });

        if (this.themeNotice)
            this.themeNotice.dispose();

        this.themeNotice = new Element("div", {
            styles: {
                fontSize: "12px",
                padding: 5,
                fontWeight: "bold",
                zIndex: 100000,
                position: "relative",
                float: "right"
            },
            html: (this.theme == "D") ? "Daytime Lemmings" : "<span style='color:#fff'>Lemmings in the Dark</span>",
            opacity: 0
        }).injectTop(this.container).fade(1);

        (function() {
            this.themeNotice.fade(0);
        }).delay(2000, this);
    },
    initialize: function(el, options) {
        this.setOptions(options);
         // daytime / night time...
        var hours = new Date().get("hr");
        this.theme = (this.options.daytime == "auto") ? (hours > 8 && hours < 16) ? "D" : "" : this.options.daytime;

        this.container = $(el);
        this.container.addEvents({
            click: function() {
                return;
                this.addLemming("r", 0, 2);
            }.bind(this)
        }).setStyles({
            overflow: "hidden"
        });

        this.coords = this.container.getCoordinates();

        this.width = this.container.getSize().x;
        this.parallax.bottomLayer = 0;


        this.parallax.topLayer = new Element("div", {
            styles: {
                position: "absolute",
                width: this.options.parallaxLayerSize,
                height: 61,
                zIndex: 1
            }
        }).inject(this.container);

        /* this.parallax.fx = new Fx.Morph(this.parallax.topLayer, {
            transition: Fx.Transitions.Sine.easeInOut
        });
        */

        this.setTheme();


        window.addEvent("resize", function() {
            this.width = this.container.getSize().x;
        }.bind(this));

    },
    setSprite: function(lem) {
        var url = (lem.exploding)
            ? "http://fragged.org/wp-content/themes/envy/images/lemming_explode_s.gif"
            : "http://fragged.org/wp-content/themes/envy/images/lemming_walk_" +lem.direction+".gif"

        lem.el.setStyles({
            marginLeft: lem.pos,
            background: "url("+url+") no-repeat 0 0"
        });
    },
    addLemming: function(direction, pos, step) {
        var lem = {
            el: new Element("div", {
                    styles: {
                        backgroundRepeat: "no-repeat",
                        width: this.options.spriteWidth,
                        height: this.options.spriteHeight,
                        position: "absolute",
                        float: "left",
                        marginTop: this.options.marginTop,
                        zIndex: this.options.spriteZindex
                    }
            }),
            direction: direction || "r",
            pos: pos || 0,
            step: step || 1
        };

        lem.el.inject(this.container);

        lem.el.addEvents({
            mouseenter: function() {
                lem.el.store("step", lem.step);

                // experimental.
                /*
                lem.step++;
                lem.direction = lem.direction == "r" ? "l" : "r";
                this.setSprite(lem);
                this.lemmingChat(lem);
                return;*/
                // end experimental

                lem.step = 0;
                this.lemmingChat(lem);
            }.bind(this),
            mouseleave: function() {
                // experimental
                /*
                lem.step = lem.el.retrieve("step");
                var chat = lem.el.getFirst();
                chat.fade(0);
                return;
                */
                // end experimental

                lem.direction = lem.direction == "r" ? "l" : "r";
                this.setSprite(lem);
                lem.step = lem.el.retrieve("step");
                var chat = lem.el.getFirst();
                chat.fade(0);

            }.bind(this),
            click: function() {
                this.explodeLemming(lem);
            }.bind(this)
        });

        this.setSprite(lem);
        this.lemmings.push(lem);
    },
    lemmingChat: function(lem, what) {
        what = what || ["?","!", "#", "@", "no"].getRandom();
        lem.el.empty();
        new Element("div", {
            "class": "lemChat",
            html: "<div>"+what+"</div>",
            opacity: 0
        }).inject(lem.el).fade(1);
    },
    moveLemmings: function() {
        this.timer = this.drawWorld.periodical(this.options.drawSpeed, this);
        // this.startParallax();
    },
    explodeLemming: function(lem) {
        lem.exploding = true;
        this.setSprite(lem);
        lem.el.removeEvents();
        (function() {
            lem.el.fade(0);
        }).delay(1000, this);

        return;
        (function() {
            this.addLemming("r", $random(0, this.width - this.options.spriteWidth), lem.step);
        }).delay(3000, this);
    },
    firework: function(x, y) {
        this.num_firework++;
        var i = this.fireworks.length;
        var colors = ['#ffffff','#ffff00','#00ff00','#ff0000','#0000ff','#ff00ff','#00ffff'], fw = [];

        var j = 20, f, a, s;

        while(j--) {
            a = Math.random() * 6.294;
            s = (Math.random() >.6) ? 4 : Math.random() * 4;

            f = new Element("div", {
                "class": "spark",
                styles: {
                    background: colors[Math.floor(Math.random()*7)],
                    top: y,
                    left: x
                },
                y: y,
                x: x,
                dx: s * Math.sin(a),
                dy: s * Math.cos(a) - 4
            }).inject(this.container);

            fw[j] = f;

        }
        this.fireworks.push(fw);
        this.running = false;

        this.runFirework(fw);
    },
    runFirework: function(fw) {
        fw.each(function(f) {
            if ($type(f) !== "element")
                return;

            var y = f.get("y").toFloat(), x = f.get("x").toFloat(), dx = f.get("dx").toFloat(), dy = f.get("dy").toFloat();
            // console.log(y, x, dy, dx);
            y += dy += 0.18;
            x += dx;

            f.set({
                y: y,
                x: x
            });

            var op = f.getStyle("opacity").toFloat() - .05;
            if (y < this.coords.top || y > this.coords.bottom || x < this.coords.left || x > this.coords.right || op <= 0) {
                // console.info("disposing of ", f, y);
                f.dispose();
                fw.erase(f);
            }
            else {

                f.set({
                    styles: {
                        top: y,
                        left: x
                    },
                    opacity: op
                });

            }
        }, this);

        if (fw.length)
            (function() {
                this.runFirework(fw);
            }).delay(this.options.drawSpeed, this);
    },


    /*
    startParallax: function() {
        this.parallax.bounds = {
            start: Math.round(this.width / 3 - 20)
        };
        this.parallax.bounds.end = Math.round(this.parallax.bounds.start + 140);

        this.parallax.fx.setOptions({
            duration: this.options.drawSpeed * this.width / this.lemmings[0].step
        });

        console.log(this.options.drawSpeed * this.width / this.lemmings[0].step);
        console.log([((this.lemmings[0].direction == "r") ? this.parallax.bounds.start : this.parallax.bounds.end) + "px 0", ((this.lemmings[0].direction == "r") ? this.parallax.bounds.end : this.parallax.bounds.start) + "px 0"]);
        this.parallax.fx.start({
            "background-position": [((this.lemmings[0].direction == "r") ? this.parallax.bounds.start : this.parallax.bounds.end) + "px 0", ((this.lemmings[0].direction == "r") ? this.parallax.bounds.end : this.parallax.bounds.start) + "px 0"]
        });
    },*/
    drawWorld: function() {
        this.lemmings.each(function(lem, i) {
            // is the lemming exploding?
            if (lem.exploding) {
                var spriteOffset = lem.el.getStyle("backgroundPosition") || 0, spriteOffsetX = spriteOffset.split(" ")[0].toInt();
                var newOffset = (spriteOffsetX - this.options.spriteWidth <= this.options.spriteExplodeContainerWidth.neg()) ? 0 : spriteOffsetX - this.options.spriteWidth;

                if (newOffset == 0 && spriteOffsetX != 0) {
                    var coords = lem.el.getPosition();
                    this.firework(coords.x + this.options.spriteWidth / 2, coords.y + this.options.spriteHeight / 2);
                    this.lemmings[i].exploding = false;
                    return;
                }

                lem.el.setStyles({
                    backgroundPosition: newOffset + "px 0px"
                });
                return;
            }

            // walking animation...
            var spriteOffset = lem.el.getStyle("backgroundPosition") || 0, spriteOffsetX = spriteOffset.split(" ")[0].toInt();
            var newOffset = (spriteOffsetX - this.options.spriteWidth <= this.options.spriteContainerWidth.neg()) ? 0 : spriteOffsetX - this.options.spriteWidth;

            if (lem.pos > this.width - this.options.spriteWidth)
                lem.pos = this.width - this.options.spriteWidth;

            // moving on-screen
            if (lem.direction == "r" && lem.step != 0) {
                this.parallax.bottomLayer++;
                if (lem.pos + this.options.spriteWidth < this.width) {
                    var nl = lem.pos + lem.step;
                    // actually move the sprite here
                    lem.el.setStyles({
                        marginLeft: nl,
                        backgroundPosition: newOffset + "px 0px"
                    });
                    this.lemmings[i].pos = nl;
                }
                else {
                    this.fireEvent("turn", "left");
                    this.lemmings[i].direction = "l";
                    this.setSprite(lem);
                    // console.log("turning...");
                }
            }
            else if (lem.step != 0) {
                // console.log(pos.left);
                var newOffset = (spriteOffsetX - this.options.spriteWidth <= this.options.spriteContainerWidth.neg()) ? 0 : spriteOffsetX - this.options.spriteWidth;
                this.parallax.bottomLayer--;
                if (lem.pos > 0) {
                    var nl = lem.pos - lem.step;
                    // actually move the sprite here
                    lem.el.setStyles({
                        marginLeft: nl,
                        backgroundPosition: newOffset + "px 0px"
                    });
                    this.lemmings[i].pos = nl;
                }
                else {
                    this.fireEvent("turn", "right");
                    this.lemmings[i].direction = "r";
                    this.setSprite(lem);
                }
            }


            // parallax effect on background
            this.container.setStyle("background-position", this.parallax.bottomLayer + "px 0");

            // progress is relational to sun.

            if (nl != 0)
                var progress = (this.width / 2) - nl / 2;

            if (!isNaN(progress))
                this.parallax.topLayer.setStyle("background-position", progress +"px 0");


            var hours = new Date().get("hr");
            // auto swap between themes
            if (this.options.daylightDetect) {
                if (hours > 8 && hours < 16 && this.theme != "D") {
                    // 8am, daylight has come!
                    this.theme = "D";
                    this.changeDaylight();
                }
                if (hours < 8 && hours > 16 && this.theme == "D") {
                    this.theme = "";
                    this.changeDaylight();
                }
            };

        }, this);
    },
    changeDaylight: function() {
        if (Browser.Engine.trident)
            this.parallax.topLayer.setOpacity(0);

        this.container.fade(.3);
        (function() {
            this.setTheme();
        }).delay(300, this);

        (function() {
            this.container.fade(1);
        }).delay(600, this);

        if (Browser.Engine.trident)
        (function() {
            this.parallax.topLayer.fade(1);
        }).delay(900, this);
    }
});

Number.implement({
    neg: function() {
        return this * -1;
    }
});

