(function($) {

    if (typeof $.Artemis != "object" || $.Artemis === null) { $.Artemis = {}; }
    if (typeof $.Artemis.Controls != "object" || $.Artemis.Controls === null) { $.Artemis.Controls = {}; }


    //------// ImageRotator Plugin \\------\\
    $.Artemis.Controls.ImageRotator = function(options) {

        /// <summary>Attaches all client-side functionality of the Artemis ImageRotator custom Javascript control to a selection of elements.</summary>
        /// <param name="options" optional="true" type="object" mayBeNull="true">The option values that the plugin will operate accoridng to.</param>

        // Merge the provided options with the default into an object, overriding defaults with provided option values.
        options = $.extend({}, $.Artemis.Controls.ImageRotator.defaults, options);


        // Define all of the plugin methods. These methods are attached directly on to the selected DOM elements 
        // and can only be accessed by referencing the DOM element from a jQuery selector object.
        var methods = {

            start: function() {
                if (!this.interval)
                {
                    var self = this;
                    this.interval = setInterval(function() {
						if (!self.paused)
						{
							self.next();
						}
					}, options.interval);
                }
            },


            stop: function() {
                if (this.interval) 
                {
                    clearInterval(this.interval);
                    this.interval = null;
                }
            },


            next: function() {
                if (this.images.length <= 1) { return; }

                if (this.currentImage.index >= this.images.length - 1) 
                {
                    this.showImage(0);
                }
                else 
                {
                    this.showImage(this.currentImage.index + 1);
                }
            },


            previous: function() {
                if (this.images.length <= 1) { return; }

                if (this.currentImage.index <= 0) 
                {
                    this.showImage(this.images.length - 1);
                }
                else 
                {
                    this.showImage(this.currentImage.index - 1);
                }
            },


            showImage: function(imageIndex) {
                var self = this;
                
                if (this.currentImage)
                {
                    $(this.currentImage).fadeOut(options.speed, function() {
                        self.currentImage = self.images[imageIndex];
                        $(self.currentImage).fadeIn(options.speed);
                        self.setTitle(self.currentImage.alt);
                    });
                }
                else
                {
                    self.currentImage = self.images[imageIndex];
                    $(self.currentImage).fadeIn(options.speed);
                    self.setTitle(self.currentImage.alt);
                }
            },
            
            
            setTitle: function(title) {
                if (options.title)
                {
                    $(options.title).html(title);
                }
            }

        };


        // Initialize the plugin against the selected elements.
        $(options.container).each(function() {

            var self = $(this);

            // Attach all of the methods to the element in context.
            $.each(methods, function(i) {
                self[0][i] = this;
            });


            var selectedImages = self.children(options.image).hide();
            self[0].images = [];


            function preloadImage(imageIndex) {
                if (selectedImages.length == 0 || imageIndex > selectedImages.length - 1) { return; }

				var image = null;
				
				if (options.width && options.height)
				{
					image = new Image(options.width, options.height);
				}
				else
				{
					image = new Image();
				}

                image.index = imageIndex;

                // Set the "load" event handler of the new image. This handler executes asynchronously, 
                // causing all images after the first one to load one by one, asynchronously, allowing 
                // the rest of the plugin to load, and all scripts declared in the document after it, 
                // without any latency.
                $(image).load(function(event) {
                    self[0].images[this.index] = image;
                    self.append($(this));

                    if (this.index == 0) 
                    {
                        self[0].showImage(0);
						self[0].start();
                    }

                    preloadImage(this.index + 1);
                });

                $(image).hide();


                // Set the "src" property of the buffered image.
                if (options.urlAttr.toLowerCase() === "html") 
                {
                    image.src = $(selectedImages[imageIndex]).html();
                }
                else 
                {
                    image.src = $(selectedImages[imageIndex]).attr(options.urlAttr);
                }


                // Set the "alt" property of the buffered image.
                if (options.titleAttr.toLowerCase() === "html") 
                {
                    image.alt = $(selectedImages[imageIndex]).html();
                }
                else 
                {
                    image.alt = $(selectedImages[imageIndex]).attr(options.titleAttr);
                }
            }


            // Recursively load the images from all selected image elements.
            preloadImage(0);
            
            
            // Attach all event handlers.
            if (options.pause)
            {
                self.hover(function(event) {
                    self[0].paused = true;
                }, function(event) {
                    self[0].paused = false;
                });
            }
            
            if (options.prev)
            {
                $(options.prev).click(function(event) {
                    event.preventDefault();
                    
                    self[0].stop();
                    self[0].previous();
                    self[0].start();
                });
            }
            
            if (options.next)
            {
                $(options.next).click(function(event) {
                    event.preventDefault();
                    
                    self[0].stop();
                    self[0].next();
                    self[0].start();
                });
            }
            
            if (options.start)
            {
                $(options.start).click(function(event) {
                    event.preventDefault();

                    self[0].start();
					self[0].paused = false;
                });
            }
            
            if (options.stop)
            {
                $(options.stop).click(function(event) {
                    event.preventDefault();

                    self[0].stop();
					self[0].paused = false;
                });
            }
        });
    };


    $.Artemis.Controls.ImageRotator.defaults = {
        container: ".artemis_image_rotator",
        image: "a",
        titleAttr: "html",
        urlAttr: "href", 
        interval: 3000,
        speed: 600,
        pause: true,
        prev: null,
        next: null,
        start: null,
        stop: null,
        title: null,
        height: null,
        width: null
    };
    
    
    /* 
        Options:
        
            container - A jQuery selector expression, jQuery object, or DOM object that represents the 
                        element(s) that contain the references to the images to be displayed by 
                        the rotator. { ".artemis_image_rotator" by default }
            image - A jQuery selector expression, jQuery object, or DOM object that represents the 
                    element(s) that reference an image to be displayed by the rotator. { "a" by default }
			titleAttr - The attribute name of a referenced image's HTML element whose value will be used 
						as the title of the image when displayed by the rotator. Can be any valid HTML 
						element attribute or specifically "html" which will reference the selected 
						element's innerHTML property. { "html" by default }
			urlAttr - The attribute name of a referenced image's HTML element whose value will be used 
					  as the source URL of the image when displayed by the rotator. Can be any valid HTML 
					  element attribute or specifically "html" which will reference the selected element's 
					  innerHTML property. { "href" by default }
			interval - The interval at which (in miliseconds) images are rotated. 
					   { any positive integer (7000 is default) }
			speed - The timespan (in miliseconds) of the fading animation as images are rotated. 
					{ any positive integer (500 is default) | "fast" | "slow" | "normal" }
			pause - Whether or not the rotation interval will be paused when the mouse cursor is hovering 
					over the selected container element(s). { true (default) | false } 
			prev - A jQuery selector expression, jQuery object, or DOM object that represents a button  
                   that will rotate to the previous image.
			next - A jQuery selector expression, jQuery object, or DOM object that represents a button  
                   that will rotate to the next image.
			start - A jQuery selector expression, jQuery object, or DOM object that represents a button  
                    that will start image rotation from a stopped or paused state.
			stop - A jQuery selector expression, jQuery object, or DOM object that represents a button  
                   that will stop image rotation from an active, unpaused state.
			title - A jQuery selector expression, jQuery object, or DOM object that represents an element   
                    displaying the title of the current image being displayed by the rotator.
			height - The forced height of the images when displayed by the rotator. The "width" option 
					 must be specified as well in order for the height to be overriden.
			width - The forced width of the images when displayed by the rotator. The "height" option 
					must be specified as well in order for the width to be overriden.
			
			
		
		Example:
		
			$(document).ready(function() {
				$.Artemis.Controls.ImageRotator({
					next: ".next",
					prev: ".prev",
					title: ".title",
					interval: 5000
				});
			});
    */    
    //------\\ ImageRotator Plugin //------//

})(jQuery.noConflict());