var Slider = new Class({

    Implements: [Options],

    numNav: new Array(), 	            //will store number nav elements (if used)
    timer: null, 				        //periodical function variable holder
    isSliding: 0, 				        //flag for animation/click prevention
    direction: 1, 			        	//flag for direction (forward/reverse)
    slideNavActive: false, 	         	//Whether or not the navigation buttons will be shown
    itemsAmount: 0, 			    	//Number of items to slide
    caption: null, 				        //Caption div
    captionHeight: 0, 				    //Caption height

    //options
    options: {
        slideTimer: 8000,  			    //Time between slides (1 second = 1000), a.k.a. the interval duration
        slideFirst: true,  			    //Slide the first slide on page load or just show it
        orientation: 'horizontal',      //vertical, horizontal, or none: None will create a fading in/out transition.
        fade: false,                    //if true will fade the outgoing slide - only used if orientation is != None
        isPaused: false, 		    	//flag for paused state
        pauseOnHover: true, 	        //Pause the slider when the user hovers over the slider
        transitionTime: 1100, 		    //Transition time (1 second = 1000)
        transitionType: 'cubic:out',    //Transition type
        container: null, 			    //container element
        items: null, 					//Array of elements for sliding
        itemNum: 0, 					//Current item number
        captions: false, 			    //Show captions
        captionsAnimate: false, 		//Animate the captions
        captionsLink: false, 		    //Show the caption read more link
        captionsLinkText: 'Read More', 	//The text for the read more link
        slideNav: null, 		        //Element that holds the number navigation
        slideNavType: 'numbers',        //Type of navigation buttons; numbers(default and fallback), titles (h3/h4) or thumbs(img.thumb).
        playBtn: null, 				    //Play/pause button element
        prevBtn: null, 			     	//Previous button element
        nextBtn: null					//Next button element
    },


    initialize: function (options) {
        var self = this;

        this.setOptions(options);

        // Number of items in the slider
        self.itemsAmount = self.options.items.length;


        /* Nigel Edit - create caption area */
        if (self.options.captions == true) {
            var captionDIV = new Element('div', {
                id: 'caption'
            }).inject(self.options.container);
            var captionHeight = captionDIV.getSize().y;
            captionDIV.setStyle('height', 0);

            self.caption = captionDIV;
            self.captionHeight = captionHeight;
        }


        //remove any scrollbar(s) on the container
        self.options.container.setStyle('overflow', "hidden");

        // Nigel edit - Does not setup navigation buttons or slide animations if there is only one item and hides nav buttons
        if (self.itemsAmount > 1) {

            // Nigel edit - Pause slider when you over over the slide if not already paused on startup
            if (self.options.isPaused == false && self.options.pauseOnHover == true) {
                self.options.container.addEvents({
                    'mouseenter': function () { self.pauseIt(); },
                    'mouseleave': function () { self.pauseIt(); }
                });

                if (self.options.captions == true) {
                    self.caption.addEvents({
                        'mousehover': function () { self.pauseIt(); }
                    });
                }
            }


            //if there is a play/pause button, set up functionality for it
            if (self.options.playBtn != null) {
                self.options.playBtn.addEvents({
                    'click': function () {
                        self.pauseIt('playBtn');
                    }
                });
            }

            //if there is a prev & next button, set up functionality for them
            if (self.options.prevBtn && self.options.nextBtn) {

                self.options.prevBtn.addEvents({
                    'click': function () {
                        if (self.isSliding == 0) {
                            if (self.options.isPaused == false) {
                                $clear(self.timer);
                                self.timer = self.slideIt.periodical(self.options.slideTimer, self, null);
                            }
                            self.direction = 0;
                            self.slideIt();
                        }
                    }
                });

                this.options.nextBtn.addEvents({
                    'click': function () {
                        if (self.isSliding == 0) {
                            if (self.options.isPaused == false) {
                                $clear(self.timer);
                                self.timer = self.slideIt.periodical(self.options.slideTimer, self, null);
                            }
                            self.direction = 1;
                            self.slideIt();
                        }
                    }
                });
            }


            // if there is a slide nav, set up flag to show its active
            if (self.options.slideNav != null) self.slideNavActive = true;


            //setup items (a.k.a. slides) from list
            self.options.items.each(function (el, i) {

                //f.y.i.  el = the element, i = the index
                el.setStyle('position', "absolute");
                var itemH = el.getSize().y;
                var itemW = el.getSize().x;
                if (self.options.orientation == 'vertical') {
                    el.setStyle('top', (-1 * itemH));
                    el.setStyle('left', 0);
                } else if (self.options.orientation == 'none') {
                    el.setStyle('left', 0);
                    el.setStyle('top', 0);
                    el.set('opacity', 0);
                } else {
                    el.setStyle('left', (-1 * itemW));
                }
                // -- Number nav setup
                if (self.slideNavActive == true) {

                    // Nigel Edit - Remove empty first element used to validate css
                    var firstElement = self.options.slideNav.getFirst('li');
                    if (firstElement && firstElement.getProperty('id') == null) firstElement.dispose();

                    // Nigel Edit - Uses numbers by default then slide header(h3 or h4) or thumbnails if available
                    var navHeading;
                    if (self.options.slideNavType == 'titles' && ($(el).getElement('h3') != null || $(el).getElement('h4') != null)) {
                        if ($(el).getElement('h3') != null) {
                            navHeading = $(el).getElement('h3').get('html');
                        } else {
                            navHeading = $(el).getElement('h4').get('html');
                        }
                    } else if (self.options.slideNavType == 'thumbs' && $(el).getElement('img.thumb') != null) {
                        navHeading = '<img src="' + $(el).getElement('img.thumb').get('src') + '" />';
                    } else {
                        navHeading = (i + 1);
                    };


                    //create numbered navigation boxes, and insert into the navigation ul
                    var numItem = new Element('li', { id: 'num' + i });
                    var numLink = new Element('a', { 'html': navHeading });

                    numItem.adopt(numLink);
                    self.options.slideNav.adopt(numItem);
                    self.numNav.push(numLink);

                    numLink.addEvents({
                        'click': function () {
                            self.numPress(i);
                        }
                    });

                    //set initial number to active state
                    if (i == self.options.itemNum) {
                        var initNum = self.numNav[i];
                        initNum.addClass('active');
                    }
                }

            });

        } else {
            if (self.options.playBtn != null) self.options.playBtn.setStyle('display', "none");
            if (self.options.prevBtn != null) self.options.prevBtn.setStyle('display', "none");
            if (self.options.nextBtn != null) self.options.nextBtn.setStyle('display', "none");
            if (self.options.slideNav != null) self.options.slideNav.setStyle('display', "none");
        }

    },


    //startup method
    start: function () {

        var self = this;
        if (self.itemsAmount > 0) {

            self.slideIt(self.options.itemNum, 0);  //initialize first slide

            // Nigel edit - Only rotate if there is more than 1 item and only change the play button text if it contains text
            if (self.itemsAmount > 1 && self.options.isPaused == false) {
                self.timer = self.slideIt.periodical(self.options.slideTimer, self, null);
                if (self.options.playBtn) {
                    if (self.options.playBtn.get('text') != '') self.options.playBtn.set('text', 'Pause');
                    self.options.playBtn.addClass('active');
                }
            }
            else {
                if (self.options.playBtn && self.options.playBtn.get('text') != '') self.options.playBtn.set('text', 'Play');
            }
        }
    },


    slideIt: function (passedID, firstslide) {

        var self = this;

        //get item to slide out
        var curItem = self.options.items[self.options.itemNum];
        if (self.slideNavActive == true) {
            var curNumItem = self.numNav[self.options.itemNum];
        }

        //check for passedID presence
        if (passedID != null) {
            if (self.options.itemNum != passedID) {
                if (self.options.itemNum > passedID) {
                    self.direction = 0;
                } else {
                    self.direction = 1;
                }
                self.options.itemNum = passedID;
            }
        }
        else {
            self.changeIndex();
        }


        //now get item to slide in using new index
        var newItem = self.options.items[self.options.itemNum];
        if (self.direction == 0) {
            var curX = self.options.container.getSize().x;
            var newX = (-1 * newItem.getSize().x);
            var curY = self.options.container.getSize().y;
            var newY = (-1 * newItem.getSize().y);
        }
        else {
            var curX = (-1 * self.options.container.getSize().x);
            var newX = newItem.getSize().x;
            var curY = (-1 * self.options.container.getSize().y);
            var newY = newItem.getSize().y;
        }


        //add/remove active number's highlight
        if (self.slideNavActive == true) {
            var newNumItem = self.numNav[self.options.itemNum];
            newNumItem.addClass('active');
        }


        var caption_title = ''; var caption_text = ''; var caption_link = ''; var caption_link_button = ''; var caption = '';

        //set up our animation stylings
        var item_in = new Fx.Morph(newItem, {
            duration: self.options.transitionTime,
            transition: self.options.transitionType,
            link: 'ignore',

            onStart: function () {
                self.isSliding = 1;  //prevents extra clicks

                // Nigel Edit - Animate captions if option is true and alt exists on the image, if alt doesnt exist dont show caption
                if (self.options.captions == true && self.options.items[self.options.itemNum].getElement('img').get('alt')) {

                    caption_title = self.options.items[self.options.itemNum].getElement('img').get('alt');
                    caption_text = self.options.items[self.options.itemNum].getElement('img').get('longdesc');
                    // Nigel Edit - If there is a link add it to the caption title 
                    if (self.options.items[self.options.itemNum].getElement('a')) {
                        caption_link = self.options.items[self.options.itemNum].getElement('a').get('href');
                        caption_title = '<a href="' + caption_link + '">' + caption_title + '</a>';
                        caption_link_button = (self.options.captionsLink ? '<a href="' + caption_link + '" class="button_view">' + self.options.captionsLinkText + '</a>' : '')
                    }
                    caption = '<h3>' + caption_title + '</h3><p>' + (caption_text ? caption_text + '<br />' : '') + caption_link_button + '</p>';


                    if (self.options.captionsAnimate == true) {
                        self.caption.set('tween', {
                            onComplete: function () {
                                self.caption.set('tween', {
                                    onComplete: $empty
                                }).tween('height', self.captionHeight);

                                self.caption.set('html', caption);
                            }
                        }).tween('height', 0);


                    } else {

                        self.caption.set('tween', { duration: 0,
                            onComplete: function () {
                                var instantshow = new Fx.Tween(self.caption).set('height', self.captionHeight);
                                self.caption.set('html', caption);
                            }
                        }).tween('height', 0);
                    }

                } else {
                    if (self.options.captions == true) self.caption.set('tween', { onComplete: $empty }).tween('height', 0);
                }
            },

            onComplete: function () {
                self.isSliding = 0;  //prevents extra clicks
            }

        });


        // Nigel edit - Dont animate slide in if there is only one item
        if (self.itemsAmount > 1) {

            // Nigel edit - Dont animate the first slide just show it
            if (self.options.itemNum == 0 & firstslide == 0 & self.options.slideFirst == false) { item_in.start({ 'opacity': [1, 1], 'left': [0, 0], 'top': [0, 0] }); }

            if (self.options.orientation == 'vertical') {
                if (self.options.fade == true) { item_in.start({ 'opacity': [0, 1], 'top': [newY, 0] }); }
                else { item_in.start({ 'top': [newY, 0] }); }
            } else if (self.options.orientation == 'none') {
                item_in.start({ 'opacity': [0, 1] });
            } else {
                if (self.options.fade == true) { item_in.start({ 'opacity': [0, 1], 'left': [newX, 0] }); }
                else { item_in.start({ 'left': [newX, 0] }); }
            }


            if (curItem != newItem) {
                var item_out = new Fx.Morph(curItem, {
                    duration: self.options.transitionTime,
                    transition: self.options.transitionType,
                    link: 'ignore'
                });

                if (self.slideNavActive == true) {
                    curNumItem.removeClass('active');
                }

                if (self.options.orientation == 'vertical') {
                    if (self.options.fade == true) { item_out.start({ 'opacity': [0], 'top': [(curY)] }); }
                    else { item_out.start({ 'top': [(curY)] }); }
                } else if (self.options.orientation == 'none') {
                    item_out.start({ 'opacity': [1, 0] });
                } else {
                    if (self.options.fade == true) { item_out.start({ 'opacity': [0], 'left': [(curX)] }); }
                    else { item_out.start({ 'left': [(curX)] }); }
                }
            }

        };

    },


    //--------------------------------------------------------------------------------------------------------
    //supplementary functions  (mini-functions)
    //--------------------------------------------------------------------------------------------------------
    pauseIt: function (pauseCaller) {
        var self = this;

        // Nigel edit - only slide if there is more than 1 item to slide and if not currently moving
        if (self.isSliding == 0 && self.itemsAmount > 1) {
            if (self.options.isPaused == false) {
                self.options.isPaused = true;
                $clear(self.timer);
                if (self.options.playBtn != null) {
                    if (self.options.playBtn.get('text') != '') self.options.playBtn.set('text', 'Play');
                    self.options.playBtn.removeClass('active');
                }
            }
            else {
                self.options.isPaused = false;
                // Nigel edit - Start sliding agin after a 1s delay
                self.slideIt.delay(600, this);
                self.timer = self.slideIt.periodical(self.options.slideTimer, this, null);
                if (self.options.playBtn != null) {
                    if (self.options.playBtn.get('text') != '') self.options.playBtn.set('text', 'Pause');
                    self.options.playBtn.addClass('active');
                }
            }

        }

        // Nigel edit - Add or remove the pause event on the slide depending on the state of the play button
        if (pauseCaller == 'playBtn' && self.options.isPaused == true) {
            self.options.container.removeEvents('mouseenter');
            self.options.container.removeEvents('mouseleave');
        } else if (pauseCaller == 'playBtn' && self.options.isPaused == false) {
            self.options.container.removeEvents('mouseenter');
            self.options.container.removeEvents('mouseleave');

            self.options.container.addEvents({
                'mouseenter': function () {
                    self.pauseIt();
                },
                'mouseleave': function () {
                    self.pauseIt();
                }
            });
        } else { };

    },


    changeIndex: function () {
        var self = this;

        var numItems = self.itemsAmount;  //get number of slider items

        //change index based on value of 'direction' parameter
        if (self.direction == 1) {
            if (self.options.itemNum < (numItems - 1)) {
                self.options.itemNum++;
            }
            else {
                self.options.itemNum = 0;
            }
        }
        else if (self.direction == 0) {
            if (self.options.itemNum > 0) {
                self.options.itemNum--;
            }
            else {
                self.options.itemNum = (numItems - 1);
            }
        }

    },


    numPress: function (theIndex) {
        var self = this;

        if ((self.isSliding == 0) && (self.options.itemNum != theIndex)) {
            if (self.options.isPaused == false) {
                $clear(self.timer);
                self.timer = self.slideIt.periodical(self.options.slideTimer, this, null);
            }
            self.slideIt(theIndex);
        }

    }

});
