/*
 * 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", 1);    
        
        //Fade in the original image
        //Obj.animate({"opacity":1, Args.Speed);      
      }
      
      //Start effect animation
      $(EffectImageId).animate({"opacity":1}, 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 = $.data(Obj);
        
        //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);
