/**
 * @author wolf
 */


ImageContext = function ImageContext(oConfig){
	this.config = Core.apply(oConfig, {
        thumbnail: {
            minSize: 50,
            maxSize: 100
        },
        buttons: {
            prev: null,
            next: null,
			scroller: {
				opacity: 0.8,
				width: 50,
				left: "((",
				right: "))",
				size: 20
			}
        },
		delay: {
			hide: 0.5, // Time the images has to hide
			show: 2 // Time the images has to show
		},
		padding: 2, // Margin to display between two images
        gallery: true, // Can be string if gallery div exist in page ||
						// boolean, append a div under the imageContainer
		shuffle: false, // If random images on first get
		firstImage: 0 // First image to display on container when images are
						// loaded
	});

	Object.extend(this, oConfig);

    this.container = $(oConfig.container) || Core.getBody();
    this.imagePreloader = $(oConfig.preloader);
    this.imageInfo = $(oConfig.imageInfo);
	this.init();

    this.images = this.imagePreloader.select("img");
	this.images.sort(function(a, b){
		var iA = Number(a.src.substring(a.src.lastIndexOf("/") + 1, a.src.lastIndexOf(".jpg")));
		var iB = Number(b.src.substring(b.src.lastIndexOf("/") + 1, b.src.lastIndexOf(".jpg")));
		
		if (isNaN(iA) || isNaN(iB)) {
			return a.src > b.src ? 1 : -1;
		}
		
		return iA - iB;
	});

	if (this.shuffle) {
		this.images.shuffle();
	}

	if (null == this.buttons.next || null == this.buttons.prev) {
		this.setNavButtons();
	} else {
		this.buttons = {
			next: $(this.buttons.next),
			prev: $(this.buttons.prev)
		};
	}

    this.handler = {
        next: this.buttons.next.on("click", this.next, this),
        prev: this.buttons.prev.on("click", this.prev, this)
    };

	this.postInit();
};

ImageContext.prototype = {
	init: function(){
		this.container.addClassName("container");
		this.imageContainer = new Element("div", {
			id: "imageContainer",
			"class": "direct-container"
		});

		this.container.insert({
			top: this.imageContainer
		});

		this.imagePreloader.addClassName("direct-container");
		this.imagePreloader.setSize(this.imageContainer.getSize());
	},

    postInit: function(){
		var oSize = this.imageContainer.getSize();
        this.images.each(function(elImage){
			this.setLoadImage(elImage, oSize);
        }, this);

        if (true === this.gallery || "string" === typeof this.gallery) {
            this.createGallery();
        } else {
            this.gallery = false;
        }

        this.firstImage = this.getWindowHash();
		if (isNaN(this.firstImage) || this.firstImage < 0 || this.firstImage >= this.images.length) {
			this.firstImage = 0;
		}

		this.initHistoryHash();
		this.switchTo(this.firstImage);
    },

    switchTo: function(iImage, bLoaded){
        iImage = Number(iImage);
		bLoaded = !!bLoaded;
        if ((iImage < 0 || this.images.length <= iImage) || iImage === this.currentImage) {
            return false;
        }

		if (!this.images[iImage].complete && !bLoaded) {
			this.images[iImage].on("load", function(){
				this.switchTo(iImage, true);
			}, this);
			
			return;
		}


        this.clearEffects(["fade", "appear"]);

        var aoLastImage = this.imageContainer.select("img");
        if (aoLastImage.length !== 0) { // If any image currently displayed :
										// for first load
            aoLastImage.each(this.hide, this);
            if (this.gallery) {
                this.gallery.down("div.selected").removeClassName("selected");
            }
        }
        if (this.gallery) {
            this.gallery.select("div.gallery-image-container img")[iImage].up("div.gallery-image-position").addClassName("selected");
        }

		this.show(this.images[iImage]);
        this.currentImage = iImage;
		this.setWindowHash(iImage);
        this.unprotect();
    },
	
	initHistoryHash: function(){
		this.history = {};
		this.setWindowHash(this.firstImage);
		this.checkHistoryHash();
	},
	
	/**
	 * Try to get default hash informations to load well first image
	 */
	getWindowHash: function(){
		var hash = window.location.hash;
		if("" == hash)
		{
			return 0;
		}
		
		hash = hash.replace("#", "");
		return parseInt(hash, 10) - 1;			
	},
	
	setWindowHash: function(iValue){
		window.location.hash = "#" + Number(iValue+1);
		this.history.value = window.location.hash;
	},
	
	checkHistoryHash: function(){
		if (this.history.hash) {
			window.clearTimeout(this.history.hash);
		}
		
		if (this.history.value !== window.location.hash) {
			var sHash = window.location.hash;
			sHash = sHash.replace(/#/, "");

			if (!isNaN(sHash)) {
				this.switchTo(sHash-1);
			}
		}
		
		this.history.hash = this.checkHistoryHash.delegate(this).delay(0.05);
	},
	
	getCurrentImage: function(){
		return this.images[this.currentImage];
	},
	
    next: function(e){
        this.switchTo(this.currentImage + 1);
    },

    prev: function(e){
        this.switchTo(this.currentImage - 1);
    },

	hide: function(elImage){
        new Effect.Fade(elImage, {
            duration: this.delay.hide,
            queue: {
                position: "end",
                scope: "fade"
            }
        });

		this.append.delay(this.delay.hide, this.imagePreloader, elImage);
	},

	show: function(elImage){
		elImage.hide(); // Reset to display:none property
		this.append(this.imageContainer, elImage);

        new Effect.Appear(elImage, {
            duration: this.delay.show,
            queue: {
                position: "end",
                scope: "appear"
            }
        });
	},

    clearEffects: function(astrQueue){
        if("string" === typeof astrQueue){
            astrQueue = [astrQueue];
        }

        astrQueue.each(function(strQueue){
            Effect.Queues.get(strQueue).each(function(fx){
                fx.cancel();
            });
        });
    },

	/**
	 * Used to can delay dom function, unauthorized on propietary dom function
	 * 
	 * @param {Element}
	 *            elDiv
	 * @param {Element}
	 *            el
	 */
	append: function(elDiv, el) {
		elDiv.appendChild(el);
	},
	
	unprotect: function(){
        if (undefined === this.playTimeout) {
			this.buttons.prev.style.visibility = 0 === this.currentImage ? "hidden" : "visible";
			this.buttons.next.style.visibility = this.images.length - 1 === this.currentImage ? "hidden" : "visible";
// this.buttons.prev[0 === this.currentImage ? "hide" : "show"]();
// this.buttons.next[this.images.length - 1 === this.currentImage ? "hide" :
// "show"]();
            if (this.gallery) {
                this.gallery.show();
            }
            
    		if(undefined != this.imageInfo)
    		{
    			this.imageInfo.innerHTML = this.getCurrentImage().alt;
    		}
        }
	},

	protect: function(){
		this.buttons.prev.style.visibility = "hidden";
		this.buttons.next.style.visibility = "hidden";
		
        if (this.gallery) {
            this.gallery.hide();
        }
        if(this.imageInfo)
        {
        	this.imageInfo.innerHTML = "";
        }
	},
	
	createGallery: function(){
		var fnPrivateSwitch = function(e, index){ // Used to call switch with
													// index on first argument,
													// not event object
			this.switchTo(index);
		};

        if (null !== $(this.gallery) && true !== this.gallery) {
            this.gallery = $(this.gallery);
        } else {
            this.gallery = new Element("div");
            this.container.appendChild(this.gallery);
			this.gallery.setSize({
				width: this.container.getWidth(),
				height: this.thumbnail.minSize + 6
			}).setStyle({
				marginTop: "40px"
			});
        }

        this.setGalleryContainer();

        var left = 0;
        var oThumb = {
            width: this.thumbnail.minSize,
            height: this.thumbnail.minSize
        };
        var oOver = {
            width: this.thumbnail.maxSize,
            height: this.thumbnail.maxSize
        };
		this.images.each(function(elImage, index){
            var elCont = this.getImageThumbnail(elImage);
			elCont.on("click", fnPrivateSwitch, this, index);
			elCont.setStyle({
                left: left + "px",
				width: this.thumbnail.minSize + "px",
				height: this.thumbnail.minSize + "px",
                padding: this.padding + "px"
			});

            this.gallery.appendChild(elCont);

			this.setLoadImage(elCont.down("div.gallery-image-container img"), oThumb);
            elCont.addClassOnOver("gallery-image-position-over");

            left += this.thumbnail.minSize + this.padding * 2 + 3;
		}, this);

        this.gallery.setWidth(left);
        this.scroller.setWidth(left);
        if (left > this.galGlobal.getWidth()) {
            this.setScrollButtons();
        } else { // Center element
            this.scroller.setStyle({
                left: "50%",
                marginLeft: -(left / 2) + "px"
            });
        }
	},

	setLoadImage: function(elImage, oContainerSize){
		if(!elImage.complete){
			return elImage.on("load", this.setImageAttribute, elImage, oContainerSize);
		} else {
			this.setImageAttribute.delegate(elImage, null, oContainerSize)();
			return function(){};
		}
	},

	setImageAttribute: function(e, oContainerSize){
		this.up("div.direct-container").style.display = "block";
		this.up("div.direct-container").setSize(oContainerSize);

		var oSize = this.getSize();
		this.className = oContainerSize.width / oSize.width > oContainerSize.height / oSize.height ? "full-height" : "full-width";

		if (this.className === "full-height") { // Use new getWidth/getHeight
												// because apply class change
												// style values
		    this.setStyle({
                left: (oContainerSize.width - this.getWidth()) / 2 + "px",
				top: 0
            });
		} else {
//            this.setStyle({
//				left: 0,
//                top: (oContainerSize.height - this.getHeight()) / 2 + "px"
//            });
          this.setStyle({
			left: 0,
            top: 0
	      });
		}

		this.up("div.direct-container").style.display = "";
// this.style.display = "";
	},

    getImageThumbnail: function(elImage){
        var elPos = new Element("div", {
            "class": "gallery-image-position"
        });
		var elHandler = new Element("div", {
			"class": "event-handler"
		});
        var elContainer = new Element("div", {
            "class": "gallery-image-container direct-container"
        });
        elContainer.insert(elImage.cloneNode(true));
        elPos.insert(elContainer);
		elPos.insert(elHandler);
		elHandler.on("mouseover", function(e){
			var off = elPos.cumulativeOffset();
			this.getLargerThumbnail(elImage).setStyle({
				left: ((off.left + this.thumbnail.minSize / 2) - this.thumbnail.maxSize / 2) + "px",
				top: (off.top - this.thumbnail.maxSize - 9) + "px"
			});
		}, this);
		elHandler.on("mouseout", this.hideLargerThumbnail, this);

        return elPos;
    },

	hideLargerThumbnail: function(e){
		this.largerThumbnail.down("img").un("load", this.handler.thumbnail);
		delete this.handler.thumbnail;

		this.largerThumbnail.down("img").src = "";
		this.largerThumbnail.style.display = "none";
	},

    getLargerThumbnail: function(elImage){
		var oSize = {
            width: this.thumbnail.maxSize,
            height: this.thumbnail.maxSize
        };
		if (undefined === this.largerThumbnail) {
			var elLarg = new Element("div", {
				"class": "thumb-position direct-container"
			}).setSize(oSize);

			var elRel = new Element("div", {
				"class": "thumb-container"
			});
			elRel.insert(new Element("img"));

			elRel.insert(new Element("div", {
				"class": "thumb-link"
			}));
			elLarg.insert(elRel);
			this.largerThumbnail = elLarg;
			Core.getBody().appendChild(this.largerThumbnail);
		}

		var elImg = this.largerThumbnail.down("img");
		elImg.style.display = "none";
		elImg.src = elImage.src;
		
		this.handler.thumbnail = this.setLoadImage(elImg, oSize);

        return this.largerThumbnail;
    },

    setGalleryContainer: function(){
        var elGlobal = new Element("div", {
            "class": "gal-global"
        });
        var elScroller = new Element("div", {
            "class": "gal-scroller"
        });
        var elGallery = new Element("div", {
            "class": "gallery"
        });
        this.gallery.insert(elGlobal.insert((elScroller.insert(elGallery))));

        this.scroller = elScroller;
        this.galClient = this.gallery;
        this.gallery = elGallery;
        this.galGlobal = elGlobal;

        this.galGlobal.setSize(this.galClient.getSize());

        this.scroller.setHeight(this.thumbnail.minSize + 6);
    },

	setNavButtons: function(){
		var elNext = new Element("div", {
			"class": "defaultButton nextNav"
		}).update(">>");
		var elPrev = new Element("div", {
			"class": "defaultButton prevNav"
		}).update("<<");

		this.imageContainer.insert(elNext).insert(elPrev).insert(new Element("div", {
			"class": "clr"
		}));

	    this.buttons = {
	        next: elNext,
	        prev: elPrev
	    };
	},

    setScrollButtons: function(){
        var elNext = new Element("div", {
            "class": "scrollable",
            id: "tonext"
        }).insert(new Element("div", {
			"class": "opacityContainer"
		}).insert(new Element("div", {
			"class": "opacity"
		})).insert(new Element("div", {
			"class": "text"
		}).update(this.config.buttons.scroller.right)));

        var elPrev = new Element("div", {
            "class": "scrollable",
            id: "toprev"
        }).insert(new Element("div", {
			"class": "opacityContainer"
		}).insert(new Element("div", {
			"class": "opacity"
		})).insert(new Element("div", {
			"class": "text"
		}).update(this.config.buttons.scroller.left)));

        this.galGlobal.insert(elNext).insert(elPrev);
        elNext.setStyle({
            right: 0,
            width: this.config.buttons.scroller.width + "px",
            height: (this.thumbnail.minSize + 6) + "px"
        });
        elPrev.setStyle({
            left: 0,
            width: this.config.buttons.scroller.width + "px",
            height: (this.thumbnail.minSize + 6) + "px"
        });
        elNext.down("div.opacity").setOpacity(this.config.buttons.scroller.opacity);
        elPrev.down("div.opacity").setOpacity(this.config.buttons.scroller.opacity);

        elNext.down("div.text").setStyle({
			fontSize: this.config.buttons.scroller.size + "px",
			lineHeight: (Math.ceil( (this.thumbnail.minSize + 6) / this.config.buttons.scroller.size * 100 ) - this.config.buttons.scroller.size) + "%"
		});
        elPrev.down("div.text").setStyle({
			fontSize: this.config.buttons.scroller.size + "px",
			lineHeight: (Math.ceil( (this.thumbnail.minSize + 6) / this.config.buttons.scroller.size * 100 ) - this.config.buttons.scroller.size) + "%"
		});

        elNext.on("mouseover", function(){
            this.scrollTo(-(this.scroller.getRight() - elNext.getLeft()));
        }, this);
        elPrev.on("mouseover", function(){
            this.scrollTo(elPrev.getRight() - this.scroller.getLeft());
        }, this);
        elNext.on("mouseout", this.cancelScroll, this);
        elPrev.on("mouseout", this.cancelScroll, this);
    },

    scrollTo: function(iScroll){
        if (undefined !== this.scroll || iScroll === 0) {
            return false;
        }
        var iDuration = Math.abs(Math.round(iScroll / this.thumbnail.minSize)) / 5;
        iDuration = iDuration > 1 ? iDuration : 1;

        this.scroll = new Effect.Move(this.scroller, {
            x: iScroll,
            mode: "relative",
            duration: iDuration,
            fps: 60,
            transition: Effect.Transitions.sinoidal
        });
    },
    cancelScroll: function(){
        if (undefined !== this.scroll) {
            this.scroll.cancel();
            delete this.scroll;
        }
    }
};
