/*
 * jQuery.ImageSwitch
 * Version: 1.0.2
 * http://www.hieu.co.uk/ImageSwitch/
 *
 * Copyright (c) 2009 Hieu Pham - http://www.hieu.co.uk
 * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
 * http://www.opensource.org/licenses/cddl1.php
 *
 * Date: 13/03/2009
 * Revision: 50
 */
 //This function to preload the image before using it in the function
 var Debug = function(mess, line){
	if(!$("#Debug"))
	{
		$("body").append("<div id='Debug'></div>");
	}
	if(line){
		$("#Debug").html($("#Debug").html()+"<br/>"+mess);
	}
	else{
		$("#Debug").html($("#Debug").html()+mess);
	}
};
(function($) {
    $.fn.ImageSwitch = function(Arguements, FuntionHandle) {
        var defaults = {
            Type: "FadeIn", // Type of effect to run the function
            NewImage: "", //The new image will be loaded in
            EffectOriginal: true,
            Speed: 1000, //Speed of the effect
            StartLeft: 50, //The position the effect start compare to the original position could be (-)
            StartTop: 0,
            StartOpacity: 0, //Which start opacity it would be
            EndLeft: -50, //The position the effect end compare to the original position could be (-)
            EndTop: 0,
            EndOpacity: 0, //Which start opacity it would be
            Direction: "RightLeft", //Which Way the image will be sroll
            Door1: "", //The image for the door 1
            Door2: "" //The image for the door 2
        };

        var Args = $.extend(defaults, Arguements);
        var Obj = this; // Just a way to reference to this obj in case we need to pass in another event handle
        //To specific which obj ID the effect will associate to
        var EffectID = 0;

        var EffectImageId; //The id of effect image layer : #GrpEffectImg + EffectID
        var EffectDivId1; //The id of effect div layer : #GrpEffectDiv2 + EffectID
        var EffectDivId2; //The id of effect div layer : #GrpEffectDiv2 + EffectID

        var EndFunction = function() {
            Obj.data("imageswitch", -1);
        };
        if ($.isFunction(FuntionHandle)) {
            EndFunction = function() {
                FuntionHandle();
                Obj.data("imageswitch", -1);
            };
        }
        //-----------------------------------------------------------------------------------------------------------
        //The original image will be fade out when the new image will fade in
        var FadeImage = function() {
            //Generate the effect map, move the effect map overlay the original map
            Obj.parent().append("<img class='GrpEffectImg' id='" + EffectImageId.replace("#", "") + "'/>");
            $(EffectImageId).attr("src", Obj.attr("src"));
            $(EffectImageId).css("position", "absolute");
            $(EffectImageId).css("top", Obj.position().top);
            $(EffectImageId).css("left", Obj.position().left);
            $(EffectImageId).css("opacity", 1);

            //Change image of the original map
            Obj.attr("src", Args.NewImage);

            //Need something special when user want to keep no effect for the orignal
            if (Args.EffectOriginal) {
                //Set the start opacity, as the effect will fade out we set in start at 1, vice versa for the original
                Obj.css("opacity", Args.StartOpacity);

                //Fade in the original image
                Obj.animate({ "opacity": 1 }, Args.Speed);
            }

            //Start effect animation
            $(EffectImageId).animate({ "opacity": 0 }, Args.Speed, function() {
                //Remove the effect image when finish the effect
                $(EffectImageId).remove();
                EndFunction();
            });
        };
        //-----------------------------------------------------------------------------------------------------------
        //The new image will fly from the startPosition with the StartOpacity

        var Fly = function(FlyIn) {
            //Generate the effect map, move the effect map overlay the original map
            $("body").append("<img class='GrpEffectImg' id='" + EffectImageId.replace("#", "") + "'/>");
            $(EffectImageId).css("position", "absolute");
            if (FlyIn) {
                //As the new image will fly in, so we set the effect image src = new image
                $(EffectImageId).attr("src", Args.NewImage);
                $(EffectImageId).css("top", Obj.offset().top + Args.StartTop);
                $(EffectImageId).css("left", Obj.offset().left + Args.StartLeft);
                $(EffectImageId).css("opacity", Args.StartOpacity);
                EndTop = Obj.offset().top;
                EndLeft = Obj.offset().left;
                //Change the opacity base on the input				
                EndOpacity = 1;
            } else {
                //As the old image will fly out, so we set the effect image src = new image
                //The effect image will be on top of the old image and hide the old image
                //So we could set the old image with the new src
                $(EffectImageId).attr("src", Obj.attr("src"));
                Obj.attr("src", Args.NewImage);
                $(EffectImageId).css("top", Obj.offset().top);
                $(EffectImageId).css("left", Obj.offset().left);
                $(EffectImageId).css("opacity", 1);
                EndTop = Obj.offset().top + Args.EndTop;
                EndLeft = Obj.offset().left + Args.EndLeft;
                //Change the opacity base on the input				
                EndOpacity = Args.EndOpacity;
            }
            //Let the effect start fly in
            $(EffectImageId).animate({ "opacity": EndOpacity, "top": EndTop,
                "left": EndLeft
            }, Args.Speed,
				function() {
				    Obj.attr("src", Args.NewImage);
				    $(EffectImageId).remove();
				    EndFunction();
				});
        };
        //-----------------------------------------------------------------------------------------------------------
        //The new image will scoll in and kick the old image out.
        //With the setting ScollIn = false, The original image will scroll out and reveal the new image
        var Scroll = function(ScrollIn) {
            //Save the original status so we could set it in the end
            var backup = Obj.clone(true);
            //Create a viewport for it
            Obj.wrap("<div id='GrpViewport-" + EffectID + "'></div>");
            $("#GrpViewport-" + EffectID).css("overflow", "hidden");
            $("#GrpViewport-" + EffectID).width(Obj.width());
            $("#GrpViewport-" + EffectID).height(Obj.height());
            //Generate the effect map, move the effect map overlay the original map				
            $("#GrpViewport-" + EffectID).append("<img class='GrpEffectImg' id='" + EffectImageId.replace("#", "") + "'/>");
            $(EffectImageId).css("position", "absolute");
            //Find where the Effect Image start
            var StartTop = 0;
            var StartLeft = 0;
            switch (Args.Direction) {
                case "RightLeft": StartLeft = -Obj.width(); break;
                case "LeftRight": StartLeft = Obj.width(); break;
                case "TopDown": StartTop = -Obj.height(); break;
                case "DownTop": StartTop = Obj.height(); break;
            }
            //In scroll in using the Start position, else, Set it to 0 so it could scroll out
            //Also need o set the destination of the animate different
            if (ScrollIn) {
                $(EffectImageId).attr("src", Args.NewImage);
                $(EffectImageId).css("top", StartTop);
                $(EffectImageId).css("left", StartLeft);
                $(EffectImageId).css("opacity", Args.StartOpacity);
                EndTop = 0;
                EndLeft = 0;
                //Don't change the opacity if it scroll in
                EndOpacity = 1;
            } else {
                $(EffectImageId).attr("src", Obj.attr("src"));
                $(EffectImageId).css("left", 0);
                $(EffectImageId).css("top", 0);
                Obj.attr("src", Args.NewImage);
                EndTop = StartTop;
                EndLeft = StartLeft;
                //Change the opacity base on the input				
                EndOpacity = Args.EndOpacity;
            }
            //We need to treat absolute position different					
            //In some case there're text arround the image, it could be a bit mess up
            if (Obj.css("position") != "absolute") {
                $("#GrpViewport-" + EffectID).css("position", "relative");
                Obj.css("position", "absolute");
            }
            else {
                $("#GrpViewport-" + EffectID).css("position", "absolute");
                $("#GrpViewport-" + EffectID).css("left", Obj.css("left"));
                $("#GrpViewport-" + EffectID).css("top", Obj.css("top"));
                Obj.css("top", 0);
                Obj.css("left", 0);
            }
            //if effect the original image, then move it as well
            if (Args.EffectOriginal && ScrollIn) {
                //Move the original image along
                Obj.animate({ "top": -StartTop,
                    "left": -StartLeft
                }, Args.Speed);
            }
            //Start the effect
            $(EffectImageId).animate({ "opacity": EndOpacity, "top": EndTop, "left": EndLeft }, Args.Speed,
					function() {
					    //Finish the effect, and replace the viewport with this area
					    backup.attr("src", Args.NewImage);
					    //Also remove the Attr for imageswitch
					    backup.removeAttr("imageswitch");
					    $("#GrpViewport-" + EffectID).replaceWith(backup);
					    EndFunction();
					});
        };
        //-----------------------------------------------------------------------------------------------------------
        //A door come out create an effect door close.then open the new image
        var SingleDoor = function() {
            //Save the original status so we could set it in the end
            var backup = Obj.clone(true);
            //Create a viewport for it
            Obj.wrap("<div id='GrpViewport'></div>");
            $("#GrpViewport").css("overflow", "hidden");
            $("#GrpViewport").width(Obj.width());
            $("#GrpViewport").height(Obj.height());
            //Generate the effect map, move the effect map overlay the original map				
            $("#GrpViewport").append("<div class='GrpEffectDiv' id='" + EffectDivId1.replace("#", "") + "'/>");
            $(EffectDivId1).attr("src", Args.NewImage);
            $(EffectDivId1).css("position", "absolute");
            $(EffectDivId1).css("background-color", "#FFF");
            if (Args.Door1.length > 0) {
                $(EffectDivId1).css("background", Args.Door1);
            }
            $(EffectDivId1).width(Obj.width());
            $(EffectDivId1).height(Obj.height());
            //Find where the Effect Image start
            var StartTop = 0;
            var StartLeft = 0;
            switch (Args.Direction) {
                case "RightLeft": StartLeft = -Obj.width(); break;
                case "LeftRight": StartLeft = Obj.width(); break;
                case "TopDown": StartTop = -Obj.height(); break;
                case "DownTop": StartTop = Obj.height(); break;
            }
            $(EffectDivId1).css("top", StartTop);
            $(EffectDivId1).css("left", StartLeft);

            //We need to treat absolute position different	
            if (Obj.css("position") != "absolute") {
                $("#GrpViewport").css("position", "relative");
                Obj.css("position", "absolute");
            }
            else {
                $("#GrpViewport").css("position", "absolute");
                $("#GrpViewport").css("left", Obj.css("left"));
                $("#GrpViewport").css("top", Obj.css("top"));
                Obj.css("top", 0);
                Obj.css("left", 0);
            }
            //Start Close the Door
            $(EffectDivId1).animate({ "top": 0, "left": 0 }, Args.Speed, function() {
                //Finish the first effect change the image and open the door
                Obj.attr("src", Args.NewImage);
                //Start open the door
                $(EffectDivId1).animate({ "top": StartTop, "left": StartLeft }, Args.Speed, function() {
                    //Reset style
                    backup.attr("src", Args.NewImage);
                    //Also remove the Attr for imageswitch
                    backup.removeAttr("imageswitch");
                    $("#GrpViewport").replaceWith(backup);
                    EndFunction();
                });
            });
        };
        //-----------------------------------------------------------------------------------------------------------
        //Same with single door but with this effect, there will be 2 door
        var DoubleDoor = function() {
            //Save the original status so we could set it in the end
            var orgPosition = Obj.css("position");
            var orgLeft = Obj.css("left");
            var orgTop = Obj.css("top");
            //Create a viewport for it
            Obj.wrap("<div id='GrpViewport'></div>");
            $("#GrpViewport").css("overflow", "hidden");
            $("#GrpViewport").width(Obj.width());
            $("#GrpViewport").height(Obj.height());
            //Generate the effect map, move the effect map overlay the original map				
            $("#GrpViewport").append("<div class='GrpEffectDiv' id='" + EffectDivId1.replace("#", "") + "'/>");
            $(EffectDivId1).css("position", "absolute");
            $(EffectDivId1).css("background-color", "#FFF");
            if (Args.Door1.length > 0) {
                $(EffectDivId1).css("background", Args.Door1);
            }
            $(EffectDivId1).width(Obj.width());
            $(EffectDivId1).height(Obj.height());
            //We need the second door
            $("#GrpViewport").append("<div class='GrpEffectDiv1' id='" + EffectDivId2.replace("#", "") + "'/>");
            $(EffectDivId2).css("position", "absolute");
            $(EffectDivId2).css("background-color", "#FFF");
            if (Args.Door2.length > 0) {
                $(EffectDivId2).css("background", Args.Door2);
            }
            $(EffectDivId2).width(Obj.width());
            $(EffectDivId2).height(Obj.height());

            //Find where the Effect Image start
            var StartTop = 0;
            var StartLeft = 0;
            switch (Args.Direction) {
                case "RightLeft": StartLeft = -Obj.width(); break;
                case "LeftRight": StartLeft = Obj.width(); break;
                case "TopDown": StartTop = -Obj.height(); break;
                case "DownTop": StartTop = Obj.height(); break;
            }
            $(EffectDivId1).css("top", StartTop);
            $(EffectDivId1).css("left", StartLeft);
            $(EffectDivId2).css("top", -StartTop);
            $(EffectDivId2).css("left", -StartLeft);

            //set the background for the door effect so it look different
            if (!Args.EffectOriginal) {
                $(EffectDivId1).css("background", "#FFF url(" + Args.NewImage + ") no-repeat " + -StartLeft / 2 + "px " + -StartTop / 2 + "px");
                $(EffectDivId2).css("background", "#FFF url(" + Args.NewImage + ") no-repeat " + StartLeft / 2 + "px " + StartTop / 2 + "px");
            }

            //We need to treat absolute position different					
            if (Obj.css("position") != "absolute") {
                $("#GrpViewport").css("position", "relative");
                Obj.css("position", "absolute");
            }
            else {
                $("#GrpViewport").css("position", "absolute");
                $("#GrpViewport").css("left", orgLeft);
                $("#GrpViewport").css("top", orgTop);
                Obj.css("position", "absolute");
                Obj.css("top", 0);
                Obj.css("left", 0);
            }
            //Start Close the Door
            $(EffectDivId1).animate({ "top": StartTop / 2, "left": StartLeft / 2 }, Args.Speed, function() {
                //Finish the first effect change the image and open the door
                Obj.attr("src", Args.NewImage);
                //If EffectOriginal isn't on mean two door stick into the new image, then stop here. Else carry on
                if (!Args.EffectOriginal) {
                    Obj.css("position", orgPosition);
                    Obj.css("top", orgTop);
                    Obj.css("left", orgLeft);
                    $("#GrpViewport").replaceWith(Obj);
                } else {
                    //Start open the door
                    $(EffectDivId1).animate({ "top": StartTop, "left": StartLeft }, Args.Speed, function() {
                        //Reset style
                        Obj.css("position", orgPosition);
                        Obj.css("top", orgTop);
                        Obj.css("left", orgLeft);
                        $("#GrpViewport").replaceWith(Obj);
                    });
                }
            });
            $(EffectDivId2).animate({ "top": -StartTop / 2, "left": -StartLeft / 2 }, Args.Speed, function() {
                //Finish the first effect change the image and open the door
                Obj.attr("src", Args.NewImage);
                //If EffectOriginal isn't on mean two door stick into the new image, then stop here. Else carry on
                if (!Args.EffectOriginal) {
                    EndFunction();
                } else {
                    //Start open the door
                    $(EffectDivId2).animate({ "top": -StartTop, "left": -StartLeft }, Args.Speed, function() {
                        //Run the end effect
                        EndFunction();
                    });
                }
            });
        };
        //-----------------------------------------------------------------------------------------------------------
        //The new image will flip from the back of the old one to the top
        //If FlipIn is false, then the old image will flip to the back reveal the new one
        var Flip = function(FlipIn) {
            var backup = Obj.clone(true);
            if (Obj.css("z-index") == 'auto') {
                Obj.css("z-index", 100);
            }
            //if (position different then absolute and relative then it should be relative)
            if (Obj.css("position") != "absolute") {
                Obj.css("position", "relative");
            }
            //Generate the effect map, move the effect map overlay the original map
            $("body").append("<img class='GrpEffectImg'  id='" + EffectImageId.replace("#", "") + "'/>");
            $(EffectImageId).css("position", "absolute");
            $(EffectImageId).css("top", Obj.offset().top);
            $(EffectImageId).css("left", Obj.offset().left);

            if (FlipIn) {
                $(EffectImageId).css("opacity", Args.StartOpacity);
                //So this layer will be under the original image
                $(EffectImageId).css("z-index", Obj.css("z-index") - 1);
                $(EffectImageId).attr("src", Args.NewImage);
            } else {
                $(EffectImageId).css("opacity", 1);
                //This layer will be on top the original image
                $(EffectImageId).css("z-index", Obj.css("z-index") + 1);
                //Turn in to the fake old image
                $(EffectImageId).attr("src", Obj.attr("src"));
                Obj.attr("src", Args.NewImage);

            }

            //Find where the effect layer stop
            if (Math.abs(Args.EndTop) < Obj.height() && Math.abs(Args.EndLeft) < Obj.width()) {
                EndTop = Obj.offset().top;
                EndLeft = Obj.offset().left + Obj.width();
            } else {
                EndTop = Obj.offset().top + Args.EndTop;
                EndLeft = Obj.offset().left + Args.EndLeft;
            }
            EndOpacity = 1;

            //Let the effect start, 
            $(EffectImageId).animate({ "opacity": EndOpacity, "top": EndTop,
                "left": EndLeft
            }, Args.Speed,
				function() {
				    //Now the effect image is out, move it back again
				    if (FlipIn) {
				        $(EffectImageId).css("z-index", 101);
				    } else {
				        EndOpacity = Args.EndOpacity;
				        $(EffectImageId).css("z-index", 2);
				    }
				    $(EffectImageId).animate({ "opacity": EndOpacity, "top": Obj.offset().top,
				        "left": Obj.offset().left
				    }, Args.Speed,
						function() {
						    //Restore the image to the original
						    backup.attr("src", Args.NewImage);
						    //Also remove the Attr for imageswitch
						    backup.removeAttr("imageswitch");
						    Obj.replaceWith(backup);
						    $(EffectImageId).remove();
						    EndFunction();
						});
				});
        };

        return this.each(function() {
            Obj = $(this);
            if (!Obj.ImageAnimating()) {
                EffectID = ImageSwitchMaxElementID;
                ImageSwitchMaxElementID++;
                //Mark the effect is running				
                Obj.data("imageswitch", EffectID);
                EffectImageId = "#GrpEffectImg-" + EffectID; //The id of effect image layer : #GrpEffectImg- + EffectID
                EffectDivId1 = "#GrpEffectDiv1-" + EffectID; //The id of effect div layer : #GrpEffectDiv1- + EffectID
                EffectDivId2 = "#GrpEffectDiv2-" + EffectID; //The id of effect div layer : #GrpEffectDiv2- + EffectID

                var TempImg = new Image();
                TempImg.src = Args.NewImage;
                $.ImagePreload(Args.NewImage, function() {
                    switch (Args.Type) {
                        case "FadeIn": FadeImage(); break;
                        case "FlyIn": Fly(true); break;
                        case "FlyOut": Fly(false); break;
                        case "FlipIn": Flip(true); break;
                        case "FlipOut": Flip(false); break;
                        case "ScrollIn": Scroll(true); break;
                        case "ScrollOut": Scroll(false); break;
                        case "SingleDoor": SingleDoor(); break;
                        case "DoubleDoor": DoubleDoor(); break;
                    }
                });
            }
        });
    };
})(jQuery);

//Check if a IS effect is running
(function($){
	$.fn.ImageAnimating = function(){
		if(this.data("imageswitch")>0){
			return true;
		}else{
			return false;
		}
	};
})(jQuery);
//Stop a specific the IS effect if it's running
(function($){
	$.fn.ImageStop = function(clearQueue, gotoEnd, EndFunction){
		return this.each(function(){
			if($(this).ImageAnimating()){
				var EffectID = $.data(this,"imageswitch");
				$("#GrpEffectImg-"+EffectID).stop(clearQueue, gotoEnd);
				$("#GrpEffectDiv-"+EffectID).stop(clearQueue, gotoEnd);
				$("#GrpEffectDiv1-"+EffectID).stop(clearQueue, gotoEnd);
				$(this).stop(clearQueue, gotoEnd);
				$("#GrpEffectImg-"+EffectID).remove();
				$("#GrpEffectDiv-"+EffectID).remove();
				$("#GrpEffectDiv1-"+EffectID).remove();
				if($.isFunction(EndFunction)){
					EndFunction();
				}
			}
		});
	};
})(jQuery);
//Stop all the IS effect running
(function($){
	$.ImageStopAll = function(clearQueue, gotoEnd, EndFunction){
		$(".GrpEffectImg").stop(clearQueue, gotoEnd);
		$(".GrpEffectDiv").stop(clearQueue, gotoEnd);
		$(".GrpEffectDiv1").stop(clearQueue, gotoEnd);
		$(this).stop(clearQueue, gotoEnd);
		$(".GrpEffectImg").remove();
		$(".GrpEffectDiv").remove();
		$(".GrpEffectDiv1").remove();
		$.data(this, "imageswitch", -1);
		if($.isFunction(EndFunction)){
			EndFunction();
		}
	};
})(jQuery);
//Preload a specific image
(function($){
	$.ImagePreload = function(FileName, EndFunction){
		var TempImage = new Image();
		TempImage.src = FileName;
		if($.isFunction(EndFunction)){
			$(TempImage).load(EndFunction());
		}
	};
})(jQuery);

var ImageSwitchMaxElementID = 0;
