(function($) {

    var methods = {

        /**
         * Kind of the constructor, called before any action
         * @param {Map} user options
         */
        init: function(options) {
            var form = this;
            if (form.data('jqv') === undefined || form.data('jqv') == null ) {
            		if (options.showType == 'slide') {
            			options.fadeLength = 10;
            		}
            		
                methods._saveOptions(form, options);
								
								var options = form.data('jqv');
								
                // add some styles if the sldieshow type is slide instead of fade
                if (options.showType == 'slide') {
                	$('#' + form.attr('id') + ' .ehs-slide-list').css('width', options.slideWidth * options.currentSRItems);
                	$('#' + form.attr('id') + ' .ehs-slider-item').show();
                	if ($('#' + options.maskID).length) {
                		$('#' + options.maskID).hide();
                	}
                	
                }
                if (options.showType == 'fade') {
                	// if the slideshow is fader, hide all but the first element
                	var i = 0;
                	$('#' + form.attr('id') + ' .ehs-slider-item').each(function() {
                		if (i > 0)
                			$(this).hide();
                		i++;
                		
                	});
              	}
            }
        },
        /**
         * Saves the user options and variables in the form.data
         *
         * @param {jqObject}
         *            form - the form where the user option should be saved
         * @param {Map}
         *            options - the user options
         * @return the user options (extended from the defaults)
         */
        _saveOptions: function(form, options) {
        	var userOptions = $.extend({
        				currentSRItems: 0,
                currentSRI: 1,
                divStr: 'slide-',
                maskID: 'slide-mask',
                iconID: 'slide-icon_',
                iconOnIdentifier: '-on.',
                iconOffIdentifier: '-off.',
                hideIcons: false,
                showType: 'fade',
                slideDirection: 'left',
                slideWidth: 780,
                shr_c: 0,
                op_c: 0,
                op_fc: 0,
                shr_pause: 0,
                sh_toID: null,
                pauseLength: 20,
                fadeLength: 20,
                id: null
            }, options);

            form.data('jqv', userOptions);
            return userOptions;
        },
        startShow: function() {
        	var form = this;
        	var options = form.data('jqv');
        	if (options.shr_pause == 0 && options.currentSRItems > 1) {
        		if (options.shr_c == 0) {
        			options.shr_c = 2;
        			options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('startShow', form); }, options.pauseLength);
        			return true;
        		}
        			
      			var todo = (options.showType == 'slide') ? 'animMaskSlide' : 'fadeMaskUp';
      			
	    			options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow(todo, form); }, options.fadeLength);
	    			return true;
        	}
        },
        animMaskSlide: function() {
        	var form = this;
        	var options = form.data('jqv');
        	if (options.shr_pause == 0) {
        			if ($('#' + options.divStr + options.currentSRI).length) {
        				if (options.slideDirection == 'left') {
        					options.op_c -= 10;
        					if (options.op_c <= (0 - $('#' + options.divStr + options.currentSRI).width())) {
        						options.op_c = 0 - $('#' + options.divStr + options.currentSRI).width();
        						$('#' + options.divStr + options.currentSRI).css('margin-left', options.op_c);
        						methods.movePlateToEnd.apply(form);
        						options.op_c = 0;
        						options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('startShow', form); }, options.pauseLength);
        					} else {
        						$('#' + options.divStr + options.currentSRI).css('margin-left', options.op_c);
        						options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('animMaskSlide', form); }, options.fadeLength);
        					}
        				}
        			}
        	}
        },
        movePlateToEnd: function() {
        	
        	var form = this;
        	var options = form.data('jqv');
        	options.shr_ci = options.currentSRI;
        	if ($('#' + options.divStr + options.shr_ci)) {
        		
        		var shr_ni = options.divStr + options.shr_c;
        		if ($('#' + shr_ni).length) {
        			$('#' + options.divStr + options.currentSRI).hide();
        			$('#' + options.divStr + options.currentSRI).css('margin-left', 0);
        			
        			$('#' + options.divStr + options.currentSRI).clone().attr('id', options.divStr + options.currentSRI + '-temp').appendTo('#' + options.divStr + 'list');
        			$('#' + options.divStr + options.currentSRI).remove();
        			$('#' + options.divStr + options.currentSRI + '-temp').attr('id', options.divStr + options.currentSRI);
        			$('#' + options.divStr + options.currentSRI).show();
        			options.currentSRI = options.shr_c;
        			if (!options.hideIcons) {
        				methods.swapSlideIcon.apply(form);
        			}
        		}
        		if (options.shr_c == options.currentSRItems) {
        			options.shr_c = 1;
        		} else {
        			options.shr_c++;
        		}
        	}
        },
        fadeMaskUp: function() {
        	var form = this;
        	var options = form.data('jqv');
        	if (options.shr_pause == 0) {
        		if ($('#' + options.maskID).length) {
        			if (options.op_c == 0) {
        				$('#' + options.maskID).show();
        			}
        			
        			options.op_c += 5;
        			options.op_fc += .05;
        			if (options.op_c > 100) {
        				options.op_c = 100;
        				options.op_fc = 1;
        			}
        			
        			$('#' + options.maskID).css('filter', 'alpha(opacity=' + options.op_c + ')');
        			$('#' + options.maskID).css('opacity', options.op_fc);
        			if (options.op_c == 100) {
        				methods.loadNewPlate.apply(form);
        				options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('fadeMaskDown', form); }, options.fadeLength);
        			} else {
        				options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('fadeMaskUp', form); }, options.fadeLength);
        			}
        		}
        	}
        },
        fadeMaskDown: function() {
        	var form = this;
        	var options = form.data('jqv');
        	if (options.shr_pause == 0) {
        		if ($('#' + options.maskID).length) {
        			options.op_c -= 5;
        			options.op_fc -= .05;
        			if (options.op_c < 0) {
        				options.op_c = 0;
        				options.op_fc = 0;
        			}
        			$('#' + options.maskID).css('filter', 'alpha(opacity=' + options.op_c + ')');
        			$('#' + options.maskID).css('opacity', options.op_fc);
        			if (options.op_c == 0) {
        				$('#' + options.maskID).hide();
        				options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('startShow', form); }, options.pauseLength);
        			} else {
        				options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('fadeMaskDown', form); }, options.fadeLength);
        			}
        		}
        	}
        },
        loadNewPlate: function() {
        	var form = this;
        	var options = form.data('jqv');
        	options.shr_ci = options.currentSRI;
        	if ($('#' + options.divStr + options.shr_ci)) {
        		$('#' + options.divStr + options.shr_ci).hide();
        		
        		var shr_ni = options.divStr + options.shr_c;
        		if ($('#' + shr_ni).length) {
        			$('#' + shr_ni).show();
        			options.currentSRI = options.shr_c;
        			if (!options.hideIcons) {
        				methods.swapSlideIcon.apply(form);
        			}
        		}
        		if (options.shr_c == options.currentSRItems) {
        			options.shr_c = 1;
        		} else {
        			options.shr_c++;
        		}
        	}
        },
        nextSlide: function() {
        	var form = this;
        	var options = form.data('jqv');
        	// clear the current timeout
        	window.clearTimeout(options.sh_toID);
        	
        	options.shr_c = options.currentSRI + 1;
        	if (options.shr_c > options.currentSRItems) {
        		options.shr_c = 1;
        	}
        	
        	methods.loadNewPlate.apply(form);

        	options.op_c = 0;
        	options.op_fc = 0;
        	if ($('#' + options.maskID).length) {
        		$('#' + options.maskID).css('filter', 'alpha(opacity=' + options.op_c + ')');
        		$('#' + options.maskID).css('opacity', options.op_fc);
        		$('#' + options.maskID).hide();
        	}
        	options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('startShow', form); }, options.pauseLength);
        },
        prevSlide: function() {
        	var form = this;
        	var options = form.data('jqv');
        	// clear the current timeout
        	window.clearTimeout(options.sh_toID);
        	
        	options.shr_c = options.currentSRI - 1;
        	if (options.shr_c < 1) {
        		options.shr_c = options.currentSRItems;
        	}
        	
        	methods.loadNewPlate.apply(form);

        	options.op_c = 0;
        	options.op_fc = 0;
        	if ($('#' + options.maskID).length) {
        		$('#' + options.maskID).css('filter', 'alpha(opacity=' + options.op_c + ')');
        		$('#' + options.maskID).css('opacity', options.op_fc);
        		$('#' + options.maskID).hide();
        	}
        	options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('startShow', form); }, options.pauseLength);
        },
        slideHighlight: function(boxnum) {
        	var form = this;
        	var options = form.data('jqv');
        	options.shr_pause = 1;
        	
        	// clear the current timeout
        	window.clearTimeout(options.sh_toID);
        	
        	options.shr_c = boxnum;
        	methods.loadNewPlate.apply(form);
        	
        	options.op_c = 0;
        	options.op_fc = 0;
        	if ($('#' + options.maskID).length) {
        		$('#' + options.maskID).css('filter', 'alpha(opacity=' + options.op_c + ')');
        		$('#' + options.maskID).css('opacity', options.op_fc);
        		$('#' + options.maskID).hide();
        	}
        },
        slideDeHighlight: function(boxnum) {
        	var form = this;
        	var options = form.data('jqv');
        	options.shr_pause = 0;
        	options.shr_c = boxnum+1;
        	if (options.shr_c > options.currentSRItems) {
        		options.shr_c = 1;
        	}
        	options.currentSRI = boxnum;
        	options.sh_toID = window.setTimeout(function() { $('#' + form.attr('id')).slideShow('startShow', form); }, options.pauseLength);
        },
        swapSlideIcon: function() {
        	var form = this;
        	var options = form.data('jqv');
        	//Highlight the right icon, unhighlight all others//
        	for(i=1; i <= options.currentSRItems; i++) {
        		var icn = options.iconID + i;
        		var icn 
        		showDiv = true;
        		if ($('#' + icn).length) {
        			src = $('#' + icn).attr('src');
        			var onregEx = new RegExp(options.iconOnIdentifier);
        			var offregEx = new RegExp(options.iconOffIdentifier);
        			
        			src = (i != options.shr_c) ? src.replace(onregEx, options.iconOffIdentifier) : src.replace(offregEx, options.iconOnIdentifier);
        			$('#' + icn).attr('src', src);
        		}
        	}
        },
        /**
         * Removes forbidden characters from class name
         * @param {String} className
         */
        _getClassName: function(className) {
        	return className.replace(":","_").replace(".","_");
        }
     };

    /**
     * Plugin entry point.
     * You may pass an action as a parameter or a list of options.
     * if none, the init and attach methods are being called.
     * Remember: if you pass options, the attached method is NOT called automatically
     *
     * @param {String}
     *            method (optional) action
     */
    $.fn.slideShow = function(method) {

        var form = $(this);
				if(!form[0]) { return false;  } // stop here if the form does not exist
		
        if (typeof(method) === 'string' && method.charAt(0) != '_' && methods[method]) {

            // make sure init is called once
            if(method != "loadSlide" && method != "fadeMaskUp" && method != "fadeMaskDown" && method != "startShow" && method != "slideHighlight" && method != "slideDeHighlight" && method != "nextSlide" && method != "prevSlide") 
            	methods.init.apply(form);
             
            return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            // default constructor with or without arguments
						methods.init.apply(form, arguments);
            return methods.startShow.apply(form);
        } else {
            $.error('Method ' + method + ' does not exist in jQuery.slideShow');
        }
    };
    
    
})(jQuery);
