﻿var PanelSlider = new Class({

    Implements: [Events, Options],

    options: {
        togglersAreaClass: ".togglers",
        panelsAreaClass: ".panels",
        controllerAreaClass: ".controller",
        togglerSelector: "",
        panelSelector: "",
        controllerSelector: "",
        switchDelaySeconds: 5,
        play: false,
        scrollFxOptions: {}
    },
    
    initialize: function(element, options) {
        this.setOptions(options);
        
        //Set up element refrences
        this.container = $(element);
        this.togglersContainer = this.container.getElement(this.options.togglersAreaClass);
        this.panelsContainer = this.container.getElement(this.options.panelsAreaClass);
        this.controllerContainer = this.container.getElement(this.options.controllerAreaClass);
        
        //If an selector is specifyed, use it to get the children, otherwise just get the first children
        this.togglerElements = ($chk(this.options.togglerSelector)) ? this.togglersContainer.getElements(this.options.togglerSelector) : this.togglersContainer.getChildren();
        this.panelElements = ($chk(this.options.panelSelector)) ? this.panelsContainer.getElements(this.options.panelSelector) : this.panelsContainer.getChildren();
        
        if ($chk(this.controllerContainer)) {
            this.controllerElementsArray = ($chk(this.options.controllerSelector)) ? this.controllerContainer.getElements(this.options.controllerSelector) : this.controllerContainer.getChildren();

            //Set up controls
            this.controllerElements = new Hash();
            this.controllerElementsArray.each(function(item, index, array) {
                if (item.hasClass("play")) {
                    this.controllerElements.set("play", item);
                    item.addEvent("click", this.playClick.bind(this));
                    if (this.options.play) {
                        item.set("text", "Pause")
                        this.controllerContainer.addClass("playing");
                    } else {
                        item.set("text", "Play");
                    }
                } else if (item.hasClass("next")) {
                    this.controllerElements.set("next", item);
                    item.addEvent("click", this.nextClick.bind(this));
                } else if (item.hasClass("previous")) {
                    this.controllerElements.set("previous", item);
                    item.addEvent("click", this.previousClick.bind(this));
                }
            }, this);
        }
        
        //Set the switch event on the togglers
        this.togglerElements.each(function(item, index) {
            item.store("corespondingPanel", this.panelElements[index]);
            this.panelElements[index].store("corespondingToggler", item);
            item.addEvent("click", this.togglerClick.bind(this));
        }, this);
        this.togglerElements[0].addClass("current");
        
        this.container.addEvent("mouseenter", this.containerEnter.bind(this));
        this.container.addEvent("mouseleave", this.containerLeave.bind(this));
        
        //Insert the container and styles to do the sliding
        this.panelWidth = this.panelsContainer.getSize().x;
        this.panelsContainer.setStyles({
            "width": this.panelWidth,
            "overflow": "hidden"
        });
        new Element("div", {
            styles: {
                "display": "block",
                "width": (this.panelWidth * this.panelElements.length),
                "height": "100%",
                "overflow": "hidden"
            }
        }).inject(this.panelsContainer, "top").adopt(this.panelElements);
        this.panelElements.each(function(item){
            item.setStyles({
                "width": this.panelWidth,
                "float": "left"
            });
        }, this);
        
        //Set up scroll FX
        this.options.scrollFxOptions.link = "cancel";
        this.scrollFx = new Fx.Scroll(this.panelsContainer, this.options.scrollFxOptions);
        
        //Start up timing function
        this.resetTimeout();
    },
    
    //Accepts an element or index
    changePanel: function(newPanel) {
        if ($type(newPanel) == "number") {
            newPanel = this.panelElements[newPanel];
        }
        this.scrollFx.toElement(newPanel);
        this.togglerElements.each(function(item) { item.removeClass("current"); });
        newPanel.retrieve("corespondingToggler").addClass("current");
    },
    
    //Helpers
    getDelaySeconds: function() {
        return this.options.switchDelaySeconds * 1000;
    },
    
    getCurrentPanel: function() {
        var current;
        this.togglerElements.each(function(item) {
            if (!$chk(current)) {
                if (item.hasClass("current")) {
                    current = item.retrieve("corespondingPanel");
                }
            }
        });
        return current;
    },
    
    //Slide player functions
    resetTimeout: function() {
        clearTimeout(this.switchIteration);
        if (this.options.play) {
            this.switchIteration = setTimeout(this.switchTimeFunction.bind(this), this.getDelaySeconds());
        }
    },
    
    switchTimeFunction: function() {
        var newIndex = this.panelElements.indexOf(this.getCurrentPanel()) + 1;
        if (newIndex == this.panelElements.length) { newIndex = 0; }
        this.changePanel(newIndex);
        this.resetTimeout();
    },
    
    stopPlay: function() {
        if ($chk(this.controllerContainer)) { this.controllerContainer.removeClass("playing"); }
        clearTimeout(this.switchIteration);
    },
    
    startPlay: function() {
        if ($chk(this.controllerContainer)) { this.controllerContainer.addClass("playing"); }
        this.resetTimeout();
    },
    
    //Events
    togglerClick: function(event) {
        var element = event.target;
        this.changePanel(element.retrieve("corespondingPanel"));
        event.stop();
    },
    
    containerEnter: function(event) {
        this.stopPlay();
    },
    
    containerLeave: function(event) {
        if (this.options.play) {
            this.startPlay();
        }
    },
    
    playClick: function(event) {
        var element = event.target;
        if (this.options.play) {
            this.stopPlay();
            this.options.play = false;
            element.set("text", "Play");
        } else {
            this.startPlay();
            this.options.play = true;
            element.set("text", "Pause");
        }
        event.stop();
    },
    
    nextClick: function(event) {
        var element = event.target;
        this.resetTimeout();
        var newIndex = this.panelElements.indexOf(this.getCurrentPanel()) + 1;
        if (newIndex == this.panelElements.length) { newIndex = 0; }
        this.changePanel(newIndex);
        event.stop();
    },
    
    previousClick: function(event) {
        var element = event.target;
        this.resetTimeout();
        clearTimeout(this.switchIteration);
        var newIndex = this.panelElements.indexOf(this.getCurrentPanel()) - 1;
        if (newIndex == -1) { newIndex = (this.panelElements.length - 1); }
        this.changePanel(newIndex);
        event.stop();
    }

});
