/**
 * jQuery (a)Slideshow plugin
 *
 * Copyright (c) 2008 Trent Foley
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * @author 	Anton Shevchuk AntonShevchuk@gmail.com
 * @version 0.3.1
 */
;(function($) {
    defaults  = {
        width:956,      // width in px
        height:237,     // height in px
        index:0,        // start from frame number N
        content :{
            'nextclick':false,  // bind content click next slide
            'playclick':false,  // bind content click play/stop
            'playframe':true,   // show frame "Play Now!"
            'imgresize':false,  // resize image to slideshow window
            'imgcenter':true,   // set image to center // TODO
            'imgajax'  :false,   // load images from links
            'linkajax' :true   // load html from links
        },
        controls :{         // show/hide controls elements
            'hide':false,    // show controls bar on mouse hover   
            'first':true,   // goto first frame
            'prev':true,    // goto previouse frame (if it first go to last)
            'play':true,    // play slideshow
            'next':true,    // goto next frame (if it last go to first)
            'last':true,    // goto last frame
            'help':false,    // show help message
            'counter':true  // show slide counter
        },
        slideshow :{
            'time' :3000,  // time out beetwen
            'title':false,  // show title
            'panel':true,  // show controls panel
            'play' :false, // play slideshow
            'help' :'Plugin homepage: <a href="http://slideshow.hohli.com">(a)Slideshow</a><br/>'+
                    'Author homepage: <a href="http://anton.shevchuk.name">Anton Shevchuk</a>'
            
        }
    };    
    /**
     * Create a new instance of slideshow.
     *
     * @classDescription	This class creates a new slideshow and manipulate it
     *
     * @return {Object}	Returns a new slideshow object.
     * @constructor	
     */
    $.fn.slideshow = function(settings) {

        var _slideshow = this;
        
		/*
		 * Construct
		 */
		this.each(function(){
		    
            var ext = $(this);
            
            this.playFlag = false;
            this.playId   = null;
            this.length   = 0;
            this.inited   = new Array();
            
            /**
             * Build Html
             * @method
             */
            this.build    = function () {
                
//                ext.addClass('slideshow');
                
                ext.wrapInner('<div class="slideshow"><div class="slideshow-content"></div></div>');
                ext = ext.find('.slideshow');
                
                this.length = ext.find('.slideshow-content > *').length;
                
                // build title
                if (this.options.slideshow.title) {
                    ext.prepend('<div class="slideshow-label"></div>');
                    ext.find('.slideshow-label').css('width',  this.options.width - 26 + 'px');
                }
                
                // build panel
                if (this.options.slideshow.panel) {
                    ext.append('<div class="slideshow-panel-place"><div class="slideshow-panel"></div></div>');
                    panel = ext.find('.slideshow-panel');
                    if (this.options.controls.first)
                        panel.append('<a class="first button" href="#first">First</a>');
                    
                    if (this.options.controls.prev)
                        panel.append('<a class="prev button"  href="#prev">Prev</a>');
                        
                    if (this.options.controls.play)
                        panel.append('<a class="play button"  href="#play">Play</a>');
                        
                    if (this.options.controls.next)
                        panel.append('<a class="next button"  href="#next">Next</a>');
                        
                    if (this.options.controls.last)
                        panel.append('<a class="last button"  href="#last">Last</a>');
                        
                    if (this.options.controls.help) {
                        panel.append('<a class="help button"  href="#help">Help</a>');
                        panel.prepend('<div class="slideshow-help">'+this.options.slideshow.help+'</div>');   
                        
                        panel.find('.slideshow-help').css('width',  this.options.width - 4  + 'px');
                    }
                    
                    
                    if (this.options.controls.counter) {
                        panel.append('<span class="counter">'+(this.options.index+1)+' / '+this.length+'</span>');
                    }
                
                    if (this.options.controls.hide) {
                        ext.find('.slideshow-panel-place').hover(function(){
                            $(this).find('.slideshow-panel').fadeIn();
                        }, function() {
                            $(this).find('.slideshow-panel').fadeOut();
                        });
                        
                        panel.hide();
                    }
                    
                    ext.find('.slideshow-panel-place').css('width',  this.options.width  + 'px');
                }
                
                /**
                 * Set Size Options
                 */
                ext.css('width',    this.options.width + 'px');
//                    ext.css('height',   this.options.height + 'px');

                ext.find('.slideshow-content').css('width',  this.options.width + 'px');
                ext.find('.slideshow-content').css('height', this.options.height+ 'px');
                
                /**
                 * Change children styles
                 */
                if (this.options.content.imgresize) {
                    ext.find('.slideshow-content > img').css('display',  'block');
                    ext.find('.slideshow-content > img').css('width',  '100%');
                    ext.find('.slideshow-content > img').css('height', '100%');
                }
                
                if (this.options.content.imgcenter) {
                    // TODO: image to vertical and horisontal center
                    /*
                    ext.find('.slideshow-content > img').css('position', 'relative');                
                    ext.find('.slideshow-content > img').css('left', '50%');
                    ext.find('.slideshow-content > img').css('top', ' 50%');
                    
                    ext.find('.slideshow-content > img').wrap('<span align="center"></span>');
                    */
                }
                
                ext.find('.slideshow-content > *').css('margin',   '0');
                ext.find('.slideshow-content > *').css('position', 'relative');
                ext.find('.slideshow-content > *').css('display',  'block');
                
//                    ext.find('.slideshow-content > *').css('width',    this.options.width + 'px');
//                    ext.find('.slideshow-content > *').css('height',   this.options.height+ 'px');
                
                ext.find('.slideshow-content > *:not(img)').css('width',  '100%');
                ext.find('.slideshow-content > *:not(img)').css('height', '100%');
            
                
                this.init(this.options.index);
                
                ext.find('.slideshow-content > *:not(:eq('+this.options.index+'))').hide();
                
                this.label();
                
                if (this.options.content.playframe) {
                    ext.find('.slideshow-content').append('<div class="slideshow-frame"></div>');
                    ext.find('.slideshow-content').append('<div class="slideshow-shadow"></div>');
                }
                
                this.events();
                
                return true;
            };
            
                            
            /**
             * Bind Events
             */
            this.events = function() {
                
                var _self = this;
                
                /**
                 * Go to next slide on content click (optional)
                 */ 
                if (_self.options.content.nextclick)
                ext.find('.slideshow-content').click(function(){            
                    _self.stop();         
                    _self.next();
                    return false;
                });
                
                /**
                 * Goto first slide button
                 */ 
                if (this.options.controls.first)
                ext.find('a.first').click(function(){            
                    _self.stop();
                    _self.goSlide(0);
                    return false;
                });
                
                /**
                 * Goto previouse slide button
                 */ 
                if (this.options.controls.prev)
                ext.find('a.prev').click(function(){            
                    _self.stop();
                    _self.prev();
                    return false;
                });
                
                /**
                 * Play slideshow button
                 */ 
                if (this.options.controls.play)
                ext.find('a.play').click(function(){
                    if (_self.playFlag) {
                        _self.stop();
                    } else {
                        _self.play();
                    }
                    return false;
                });
        
                /**
                 * Goto next slide button
                 */ 
                if (this.options.controls.next)
                ext.find('a.next').click(function(){
                    _self.stop();         
                    _self.next();
                    return false;
                });
                
                /**
                 * Goto last slide button
                 */ 
                if (this.options.controls.last)
                ext.find('a.last').click(function(){
                    _self.stop();
                    _self.goSlide(_self.length-1);
                    return false;
                });
                
                /**
                 * Show help message
                 */ 
                if (this.options.controls.help)
                ext.find('a.help').click(function(){
                    _self.stop();
                    ext.find('.slideshow-help').slideToggle();
                    return false;
                });
                
                /**
                 * Show playframe
                 */
                if (this.options.content.playframe) 
                ext.find('.slideshow-frame').click(function(){
                    ext.find('.slideshow-frame').remove();
                    ext.find('.slideshow-shadow').remove();
                    
                    if (_self.options.content.playclick)
                        setTimeout(function(ms){ _self.play() }, _self.options.slideshow.time);
                    return false;  
                });
            };
            
            /**
             * Find and show label of slide
             * @method
             */
            this.label = function () {
                if (!this.options.slideshow.title) return false;
                
                label = '';
                
                current = ext.find('.slideshow-content > *:visible');
                
                if (current.attr('alt')) {
                    label = current.attr('alt');
                } else if (current.attr('title')) {
                    label = current.attr('title');
                }else if (current.find('label:first').length>0) {
                            current.find('label:first').hide();
                    label = current.find('label:first').html();
                }
                
                ext.find('.slideshow-label').html(label);
            };
            
            /**
             * Goto previous slide
             * @method
             */
            this.prev = function () {
                if (this.options.index == 0) {
                    i = (this.length-1);
                } else {
                    i = this.options.index - 1;
                }
    
                this.goSlide(i);
            };
                

            /**        
             * Play Slideshow
             * @method
             */
            this.play = function () {
                this.playFlag = true;
                this._play();
                ext.find('a.play').addClass('stop');
            };
            
            /**        
             * Play Slideshow
             * @method
             */
            this._play = function () {  
                var _self = this;     
                this.next();
                if (this.playFlag) 
                    this.playId = setTimeout(function(ms){ _self._play() }, this.options.slideshow.time)
            };
            
            /**
             * Stop Slideshow
             * @method
             */
            this.stop = function () {            
                ext.find('a.play').removeClass('stop');
                this.playFlag = false;
                clearTimeout(this.playId);
            };
            
            /**
             * Goto next slide
             * @method
             */
            this.next = function () {
                if (this.options.index == (this.length-1)) {
                    i = 0;
                } else {
                    i = this.options.index + 1;
                }            
                this.goSlide(i);
            };
            
            /**        
             * Init N-slide
             * @method
             * @param {Integer} n
             */
            this.init = function (index) {
                // initialize only ones
                for (var i = 0, loopCnt = this.inited.length; i < loopCnt; i++) {
                    if (this.inited[i] === index) {
                        return true;
                    }
                }
                
                // index to inited stack
                this.inited.push(index);
                
                // current slide
                slide = ext.find('.slideshow-content > *:eq('+index+')');
                
                var _self = this; 
                /**
                 * Replace A to content from HREF
                 */
                if (slide.get(0).tagName == 'A') {
                    var href   = slide.attr('href');
                    
                    var title  = slide.attr('title');
                        title  = title.replace(/\"/i,'\'');   // if you use single quotes for tag attribs
                        
                    var domain = document.domain;
                        domain = domain.replace(/\./i,"\.");  // for strong check domain name
                    
                    var reimage = new RegExp("\.(png|gif|jpg|jpeg|svg)$", "i");
                    var relocal = new RegExp("^((https?:\/\/"+domain+")|(?!http:\/\/))", "i");
                    
                    
                    if (this.options.content.imgajax && reimage.test(href)) {
                        slide.replaceWith('<img src="'+href+'" alt="'+title+'"/>');
                    } else if (this.options.content.linkajax && relocal.test(href)) {
                        $.get(href, function(data){
                            slide.replaceWith('<div><label>'+title+'</label>'+data+'</div>');
                        });
                    } else { // nothing else
//                            slide.wrap('<span></span>');
                    }
                    
                    slide = ext.find('.slideshow-content > *:eq('+index+')');
                }
                
                /**
                 * Play/stop on content click (like image and other)
                 */
                if (this.options.content.playclick)
                $(slide).click(function(){
                    if (_self.playFlag) {
                        _self.stop();
                    } else {
                        _self.play();
                    }
                    return false;
                });
            };
            
            /**        
             * Goto N-slide
             * @method
             * @param {Integer} n
             */
            this.goSlide = function (n) {
                var _self = this;
                
                next = ext.find('.slideshow-content > *:eq('+n+')');
                
                this.init(n);
                
                ext.find('.slideshow-content > *:eq('+this.options.index+')').fadeOut('normal');
                
                this.options.index = n;
            
                next.fadeIn('normal', function () {
                    _self.label();
                    _self.counter();
                }); 
            };
            
            /**
             * Update counter data
             * @method
             */
            this.counter = function () {
                if (this.options.controls.counter)
                    ext.find('.slideshow-panel span.counter').html((this.options.index+1) + ' / ' + this.length);
                
            };
    		
    		// Now initialize the slideshow
    		this.options = $.extend({}, defaults, settings);
    		
    		if (typeof(settings) != 'undefined') {
    		    if (typeof(settings.content) != 'undefined')
        		   this.options.content = $.extend({}, defaults.content, settings.content);
        		
        		if (typeof(settings.controls) != 'undefined')
        		   this.options.controls = $.extend({}, defaults.controls,  settings.controls);
        		
        		if (typeof(settings.slideshow) != 'undefined')
        		   this.options.slideshow = $.extend({}, defaults.slideshow, settings.slideshow);
    		}

            this.build();
            
            /**
             * Show slideshow
             */
            ext.show();
            
            /**
             * Check play option
             */
            if (this.options.slideshow.play) {
                this.play();
            }
                
            return ext;
		});
		
        /**
         * external functions - append to $
         */
        _slideshow.playSlide = function(){ _slideshow.each(function () { this.play(); }) };
        _slideshow.stopSlide = function(){ _slideshow.each(function () { this.stop(); }) };
        _slideshow.nextSlide = function(){ _slideshow.each(function () { this.next(); }) };
        _slideshow.prevSlide = function(){ _slideshow.each(function () { this.prev(); }) };
		
		return this;
    }
})(jQuery);
