Fx.Elements = new Class({
    Extends: Fx.CSS,
    initialize: function(a, b) {
        this.elements = this.subject = $$(a);
        this.parent(b)
    },

    compute: function(a, b, d) {
        var c = {};

        for (var g in a) {
            var i = a[g], e = b[g], h = c[g] = {};

            for (var f in i)
                h[f] = this.parent(i[f], e[f], d)
        }
        return c
    },

    set: function(a) {
        for (var b in a) {
            var d = a[b];

            for (var c in d)
                this.render(this.elements[b], c, d[c], this.options.unit)
        }
        return this
    },

    start: function(a) {
        if (!this.check(a))
            return this;
        var b = {}, d = {};

        for (var c in a) {
            var g = a[c], i = b[c] = {}, e = d[c] = {};

            for (var h in g) {
                var f = this.prepare(this.elements[c], h, g[h]);
                i[h] = f.from;
                e[h] = f.to
            }
        }
        return this.parent(b, d)
    }
});

var Loop = new Class({
    loopCount: 0,
    isStopped: true,
    isLooping: false,
    loopMethod: $empty,
    setLoop: function(a, b) {
        if (this.isLooping) {
            this.stopLoop();
            var d = true
        }
        else d = false;
        this.loopMethod = a;
        this.loopDelay = b || 3E3;
        d && this.startLoop();
        return this
    },

    stopLoop: function() {
        this.isStopped = true;
        this.isLooping = false;
        $clear(this.periodical);
        return this
    },

    startLoop: function(a) {
        if (this.isStopped) {
            a = a ? a : this.loopDelay;
            this.isStopped = false;
            this.isLooping = true;
            this.periodical = this.looper.periodical(a, this)
        }
        return this
    },

    resetLoop: function() {
        this.loopCount = 0;
        return this
    },

    looper: function() {
        this.loopCount++;
        this.loopMethod(this.loopCount);
        return this
    }
});

var transitionDuration = getRotatingTransitionDuration();

SlideShow = new Class({
    Implements: [Options, Events, Loop],
    options:
    {
        delay: 7E3,
        transition: "crossFade",
        duration: transitionDuration,
        autoplay: false
    },

    initialize: function(a, b) {
        this.setOptions(b);
        this.setLoop(this.showNext, this.options.delay);
        this.element = document.id(a);
        this.slides = this.element.getChildren();
        this.current = this.slides[0];
        this.transitioning = false;
        this.setup();
        this.options.autoplay && this.play()
    },

    setup: function() {
        this.setupElement().setupSlides(true);
        return this
    },

    setupElement: function() {
        var a = this.element;
        a.getStyle("position") != "absolute" && a != document.body && a.setStyle("position", "relative");
        return this
    },

    setupSlides: function(a) {
        this.slides.each(function(b, d) {
            this.storeTransition(b).reset(b);
            a && d != 0 && b.setStyle("display", "none")
        }, this);
        return this
    },

    storeTransition: function(a) {
        var b = a.get("class"), d = /transition:[a-zA-Z]+/, c = /duration:[0-9]+/;
        d = b.match(d) ? b.match(d)[0].split(":")[1] : this.options.transition;
        b = b.match(c) ? b.match(c)[0].split(":")[1] : this.options.duration;
        a.store("ssTransition", d).store("ssDuration", b);
        return this
    },

    resetOptions: function(a) {
        this.options = $merge(this.options, a);
        this.setupSlides(false);
        return this
    },

    getTransition: function(a) {
        return a.retrieve("ssTransition")
    },

    getDuration: function(a) {
        return a.retrieve("ssDuration")
    },

    show: function(a, b) {
        a = typeof a == "number" ? this.slides[a] : a;

        if (a != this.current && !this.transitioning) {
            this.transitioning = true;
            var d = b && b.transition ? b.transition : this.getTransition(a), c = b && b.duration ? b.duration : this.getDuration(a), g = this.current.setStyle("z-index", 1), i = this.reset(a), e = { previous: { element: g, index: this.slides.indexOf(g) }, next: { element: i, index: this.slides.indexOf(i)} };
            this.fireEvent("show", e);
            this.transitions[d](g, i, c, this);
            (function() {
                g.setStyle("display", "none");
                this.fireEvent("showComplete", e);
                this.transitioning = false
            }).bind(this).delay(c);
            this.current = i
        }
        return this
    },

    reset: function(a) {
        return a.setStyles({ position: "absolute", "z-index": 0, display: "block", left: 0, top: 0 }).fade("show")
    },

    nextSlide: function() {
        var a = this.current.getNext();
        return a ? a : this.slides[0]
    },

    previousSlide: function() {
        var a = this.current.getPrevious();
        return a ? a : this.slides.getLast()
    },

    showNext: function(a) {
        this.show(this.nextSlide(), a);
        return this
    },

    showPrevious: function(a) {
        this.show(this.previousSlide(), a);
        return this
    },

    play: function() {
        this.startLoop();
        this.fireEvent("play");
        return this
    },

    pause: function() {
        this.stopLoop();
        this.fireEvent("pause");
        return this
    },

    reverse: function() {
        this.setLoop(this.loopMethod == this.showNext ? this.showPrevious : this.showNext, this.options.delay);
        this.fireEvent("reverse");
        return this
    },

    toElement: function() {
        return this.element
    }
});

Element.Properties.slideshow =
{
    set: function(a) {
        var b = this.retrieve("slideshow");
        b && b.pause();
        return this.eliminate("slideshow").store("slideshow:options", a)
    },

    get: function(a) {
        if (a || !this.retrieve("slideshow")) {
            if (a || !this.retrieve("slideshow:options"))
                this.set("slideshow", a);
            this.store("slideshow", new SlideShow(this, this.retrieve("slideshow:options")))
        }
        return this.retrieve("slideshow")
    }
};

Element.implement(
{
    playSlideShow: function(a) {
        this.get("slideshow", a).play();
        return this
    },

    pauseSlideShow: function(a) {
        this.get("slideshow", a).pause();
        return this
    }
});

SlideShow.adders =
{
    transitions: {},
    add: function(a, b) {
        this.transitions[a] = b;
        this.implement({ transitions: this.transitions })
    },

    addAllThese: function(a) {
        $A(a).each(function(b) {
            this.add(b[0], b[1])
        }, this)
    }
};

$extend(SlideShow, SlideShow.adders);
SlideShow.implement(SlideShow.adders);
SlideShow.add("fade",
function(a, b, d) {
    a.set("tween", { duration: d }).fade("out");
    return this
});


SlideShow.addAllThese([["none", function(a) {
    a.setStyle("display", "none");
    return this
} ],

["crossFade", function(a, b, d) {
    a.set("tween", { duration: d }).fade("out");
    b.set("tween", { duration: d }).fade("in");
    return this
} ],

["fadeThroughBackground", function(a, b, d) {
    d = d / 2;
    b.set("tween", { duration: d }).fade("hide");
    //document.getElementById('information_section').fade("hide");
    a.set("tween", { duration: d,
        onComplete: function() {
            document.getElementById('image_title').innerHTML = b.children[0].title;
            document.getElementById('image_description').innerHTML = b.children[0].alt;
            b.fade("in")
            //document.getElementById('information_section').fade("in");
        }
    }).fade("out")
} ],

["pushLeft", function(a, b, d, c) {
    c = c.element.getSize().x;
    b.setStyle("left", c);
    (new Fx.Elements([a, b], { duration: d })).start({ 0: { left: [-c] }, 1: { left: [0]} });
    return this
} ],

["pushRight", function(a, b, d, c) {
    c = c.element.getSize().x;
    b.setStyle("left", -c);
    (new Fx.Elements([a, b], { duration: d })).start({ 0: { left: [c] }, 1: { left: [0]} });
    return this
} ],

["pushUp", function(a, b, d, c) {
    c = c.element.getSize().y;
    b.setStyle("top", c);
    (new Fx.Elements([a, b], { duration: d })).start({ 0: { top: [-c] }, 1: { top: [0]} });
    return this
} ],

["pushDown", function(a, b, d, c) {
    c = c.element.getSize().y;
    b.setStyle("top", -c);
    (new Fx.Elements([a, b], { duration: d })).start({ 0: { top: [c] }, 1: { top: [0]} });
    return this
} ],

["blindRight", function(a, b, d, c) {
    a = c.element.getSize().x;
    b.setStyles({ left: -a, "z-index": 2 }).set("tween", { duration: d }).tween("left", 0);
    return this
} ],

["blindLeft", function(a, b, d, c) {
    a = c.element.getSize().x;
    b.setStyles({ left: a, "z-index": 2 }).set("tween", { duration: d }).tween("left", 0);
    return this
} ],

["blindUp", function(a, b, d, c) {
    a = c.element.getSize().y;
    b.setStyles({ top: a, "z-index": 2 }).set("tween", { duration: d }).tween("top", 0);
    return this
} ],

["blindDown", function(a, b, d, c) {
    a = c.element.getSize().y;
    b.setStyles({ top: -a, "z-index": 2 }).set("tween", { duration: d }).tween("top", 0);
    return this
} ],

["blindDownFade", function(a, b, d, c) {
    this.blindDown(a, b, d, c).fade(a, b, d, c)
} ],

["blindUpFade", function(a, b, d, c) {
    this.blindUp(a, b, d, c).fade(a, b, d, c)
} ],

["blindLeftFade", function(a, b, d, c) {
    this.blindLeft(a, b, d, c).fade(a, b, d, c)
} ],

["blindRightFade", function(a, b, d, c) {
    this.blindRight(a, b, d, c).fade(a, b, d, c)
} ]
]);

var Tabs = new Class({
    Extends: SlideShow,
    options: { transition: "none", currentClassName: "current" },
    initialize: function(a, b, d) {
        this.navs = $$(b);
        this.parent(a, d);
        this.bound = { navClick: this.navClick.bind(this), onShow: this.onShow.bind(this) };
        this.attach()
    },

    attach: function() {
        var a = this;
        this.navs.each(function(b, d) {
            b.store("tabs:handler", function() {
                a.navClick(d)
            }).addEvent("click", b.retrieve("tabs:handler"))
        }, this);
        this.addEvent("show", this.bound.onShow);
        return this
    },

    detach: function() {
        this.navs.each(function(a) {
            a.removeEvent("click", a.retrieve("tabs:handler"))
        }, this);
        return this
    },

    navClick: function(a) {
        this.show(a);
        return this
    },

    onShow: function(a) {
        this.navs[a.previous.index].removeClass(this.options.currentClassName);
        this.navs[a.next.index].addClass(this.options.currentClassName)
    }
});

(function(a) {
    a.store("hashchange:interval", 300);
    a.store("hashchange:ieframe-src", "./blank.html");
    a.store("hashchange:implemented", !!("onhashchange" in a));

    Element.Events.hashchange =
    {
        onAdd: function(b) {
            Element.Events.hashchange.onAdd = $empty;
            var d = $(this), c = $empty;

            if (d == $(a)) {
                a.store("hashchange:changed", false);
                var g = function(e, h) {
                    a.store("hashchange:current", h || e);

                    if (a.retrieve("hashchange:changed")) {
                        e = e.trim();

                        if (e.length == 0)
                            if ((new String(a.location)).indexOf("#") >= 0) e = "#";
                        a.fireEvent("hashchange", [e])
                    }
                    else a.store("hashchange:changed", true)
                };

                if (typeof a.onhashchange == "function" && b !== a.onhashchange) {
                    a.addEvent("hashchange", a.onhashchange);
                    a.onhashchange = null
                }

                if (Browser.Engine.trident4 || Browser.Engine.trident5) {
                    c = function(e, h) {
                        var f = a.retrieve("hashchange:checker"), l = a.retrieve("hashchange:timer");
                        $clear(l);
                        var j = h && e.length == 0, k = e == "#";
                        l = unescape(new String(a.location));

                        if (k) k = j = "#";
                        else if (j) k = j = "";
                        else {
                            j = e = e != null ? e : l;

                            if (e.length > 0) {
                                k = e.indexOf("#");

                                if (k >= 0) j = e.substr(k)
                            }
                            k = j.toLowerCase()
                        }

                        var m = a.retrieve("hashchange:current");

                        if (m != k) {
                            if (h) {
                                e = l;

                                if (m) e = e.replace(m, j);
                                else e += j;
                                a.location = e
                            }
                            l = !h && a.retrieve("hashchange:changed");
                            g(j, k);
                            l && a.retrieve("hashchange:ieframe").setPath(j)
                        }
                        l = f.delay(a.retrieve("hashchange:interval"));
                        a.store("hashchange:timer", l)
                    };

                    var i = a.retrieve("hashchange:ieframe-src");
                    b = new IFrame(
                    {
                        id: "hashchange-ie-frame",
                        src: i + "?start",
                        styles: { width: 0, height: 0, position: "absolute", top: -9999, left: -9999 },

                        onload: function() {
                            var e = $("hashchange-ie-frame");

                            if (e.retrieve("loaded")) {
                                e = unescape(new String(e.contentWindow.location));
                                var h = e.indexOf("?");
                                if (h >= 0) {
                                    var f = "";

                                    if (e.indexOf("?empty") >= 0)
                                        f = "#";
                                    else {
                                        h = e.indexOf("?!");

                                        if (h >= 0) {
                                            f = e.substr(h + 2);
                                            f = "#" + f
                                        }
                                    }
                                    a.retrieve("hashchange:checker")(f, true)
                                }
                            }
                            else e.store("loaded", true)
                        } .bind(a)
                    });

                    a.store("hashchange:ieframe", b);
                    b.injectInside(document.body);

                    b.setPath = function(e) {
                        if (e.charAt(0) == "#") {
                            e = e.substr(1);

                            if (e.length == 0) {
                                this.contentWindow.location = i + "?empty"; return
                            }
                        }
                        this.contentWindow.location = i + "?!" + escape(e)
                    } .bind(b)
                }
                else if (a.retrieve("hashchange:implemented"))
                    c = a.onhashchange = function(e) {
                        e = e && typeof e == "string" ? e : new String(a.location.hash);
                        g.delay(1, a, [e])
                    };
                else {
                    if (Browser.Engine.presto)
                        history.navigationMode = "compatible";

                    c = function(e) {
                        var h = a.retrieve("hashchange:checker"), f = a.retrieve("hashchange:timer");
                        $clear(f);
                        e = e || new String(a.location.hash);
                        f = e.toLowerCase();

                        if (e.length == 0 && (new String(a.location)).indexOf("#") >= 0) f = "#";
                        a.retrieve("hashchange:current") != f && g(e, f);
                        f = h.delay(a.retrieve("hashchange:interval"));
                        a.store("hashchange:timer", f)
                    }
                }
                a.store("hashchange:checker", c);
                c();

                a.sethash = function(e) {
                    if (e.charAt(0) != "#")
                        e = "#" + e; a.hashcheck(e)
                }
            }
        },

        onDelete: function() {
            if ($(this) == $(a)) {
                var b = a.retrieve("hashchange:timer");

                if (b) {
                    $clear(b);
                    a.store("hashchange:timer", null)
                }
            }
        }
    }
})(window, undefined);

var HashEvents = new Class({
    Implements: [Options, Events],
    initialize: function(a) {
        this.setOptions(a);
        this.pairs = {};
        this.lastPairs = {};
        this.bound = this.check.bind(this);
        this.attach()
    },

    attach: function() {
        window.addEvent("hashchange", this.bound);
        return this
    },

    detach: function() {
        window.removeEvent("hashchange", this.bound);
        return this
    },

    check: function() {
        this.fireEvent("change");
        this.pairs = window.location.hash.substr(1).parseHashEvents();

        for (key in this.pairs)
            if (this.lastPairs[key] && this.lastPairs[key] != this.pairs[key])
            this.fireEvent(key + ":change", this.pairs[key]);
        else this.lastPairs[key] || this.fireEvent(key, this.pairs[key]);

        for (key in this.lastPairs)
            !this.pairs[key] && this.fireEvent(key + ":remove", this.lastPairs[key]);
        this.lastPairs = this.pairs;
        return this
    },

    handleBlankKeys: function(a) {
        $type(a) == "array" ? a.each(function(b) {
            console.log(b + " added!")
        }, this) : console.log(a + " added!")
    }
});

String.implement(
{
    parseHashEvents: function() {
        var a = this.split(/[&;]/), b = {};
        a.length && a.each(function(d) {
            var c = d.split("=");
            d = c[0];
            c = c[1] || true;
            var g = $type(c) == "string" ? c.split(",") : false;
            b[d] = g && g.length > 1 ? g : c
        });
        return b
    }
});

var imageDelay = getRotatingImageDelay();

var App = new Class({

    initialize: function() {
        this.initSlideShows()
			.attach()
		;
    },

    initSlideShows: function() {
        // navigation demo with numbered labels
        this.navigationShow = new SlideShow('navigation-show', {
            transition: 'fadeThroughBackground',
            delay: imageDelay,
            autoplay: true
        });

        return this;
    },

    attach: function() {
        return this.attachNavigationDemo();
    },

    attachNavigationDemo: function() {
        var self = this;

        // these will control the slideshow
        var navs = $('navigation-demo').getElements('.sliding_images li');

        // add click events to the elements
        navs.each(function(element, index) {
            element.addEvent('click', function() {
                // going to figure the current index of the slideshow
                // and change the transition to go the "right" way
                // so it feels like a typical "panel" kind of widget
                var currentIndex = self.navigationShow.slides.indexOf(self.navigationShow.current);
                var transition = 'fadeThroughBackground';
                // ignoring the last two lines this is really
                // quite simple, the indicies of the nav elements
                // and the slide elements match ... so just show the index
                self.navigationShow.show(index, { transition: transition });
                self.navigationShow.pause();
                setTimeout(self.navigationShow.play(), imageDelay);
                // alert('clicked');
            });
        });

        // morph the style of the nav elements
        this.navigationShow.addEvent('show', function(slideData) {
            navs[slideData.previous.index].morph('.normal');
            navs[slideData.next.index].morph('.current');
        });

        // set the initial slide to current
        navs[0].morph('.current');

        // add Keyboard
        $(document).addEvent('keyup', function(event) {
            // couldn't be any easier!
            if (event.key == 'left')
                self.navigationShow.showPrevious({ transition: 'pushRight' });
            else if (event.key == 'right')
                self.navigationShow.showNext({ transition: 'pushLeft' });
        });

        return this;
    }
});

var app;
window.addEvent('domready', function(){
	$$('html')[0].removeClass('notready').addClass('ready');
	app = new App;
});
