/* -------------------------------------------------------------------------- *
 *   Experience Javascript Library (version 1.0b)
 *  (c) 2007 Ahmed Saad <ahmeds@users.sourceforge.net>
 *
 *  Experience is freely distributable under the terms of an MIT-style license.
 *  For details, see project website at http://experience.sf.net
 * -------------------------------------------------------------------------- */

// Panorama component
experience.panorama  =  {

    Version : '0.2',

    //// MNEMONICS ////////////////////////////////////////////

    ZOOM_IN : 1,
    ZOOM_OUT : -1,
    ZOOM_RESTORE_SIZE : 3, //Point to 100
    MOVE_DOWN : 1,
    MOVE_UP :  2,
    MOVE_RIGHT : 3,
    MOVE_LEFT : 4,

    Viewer : function(userParams) {
    
        //// PRIVATE FIELDS //////////////////////////////////////

        this.Params = $H({
            ZoomFactor : 0.05, // %
            MoveBy : 2, // px
            MoveRate :  15, // ms
            ReversePanning : false,
            ReverseScrolling : false, 
            InnerUpperOffset : -40, // px 
            ShowStatus : false, 
            ShowNavigator : false,
            ShowZoomSelectBox : true,
            IconDirectory : 'icons',
            IconExtension : '.gif', 
            RenderIn: null // an element or an id
        }),

        this.isBeingDragged = false;
        this.lastLeft = this.lastTop = this.lastX = this.lastY = null;
        this.originalWidth = this.originalHeight = null;
        this.timeOutId = null;
        this.isMaximizedInstance = false;
        this.onFullWindowListeners = [];
        this.onUnFullWindowListeners = [];

        //// PUBLIC METHODS //////////////////////////////////////////////////////

        this.show = experience.panorama.show;
        this.hide = experience.panorama.hide;
        this.setImage = experience.panorama.setImage;
        this.getImage = experience.panorama.getImage;
		this.doZoom = experience.panorama.doZoom;
        this.addOnFullWindowListener = experience.panorama.addOnFullWindowListener;
        this.removeOnFullWindowListener = experience.panorama.removeOnFullWindowListener;
        this.addOnUnFullWindowListener = experience.panorama.addOnUnFullWindowListener;
        this.removeOnUnFullWindowListener = experience.panorama.removeOnUnFullWindowListener;
		this.restoreImagePosition = experience.panorama.restoreImagePosition;

        //// PRIVATE METHODS /////////////////////////////////////////////////////

        this.getImageResource = experience.panorama.getImageResource;
        this.positionImage = experience.panorama.positionImage;
        this.positionCanvas = experience.panorama.positionCanvas;
        this.setStatus = experience.panorama.setStatus;
        this.fireListeners = experience.panorama.fireListeners;

        //// VALIDATION //////////////////////////////////////////////////////////

        if (
              typeof(userParams['ImageURL']) != 'undefined' &&
              (
                typeof(userParams['ImageWidth']) == 'undefined' || 
                typeof(userParams['ImageHeight']) == 'undefined'
              )
           )
        {
            throw new Error("Experience::Panorama: You have to specify ImageWidth and ImageHeight when calling " +
                              "initialize() passing an ImageURL");
        }

        //// INITIALIZATION /////////////////////////////////////////////

        this.Params.merge(userParams);
        
        // construct canvas and all
        this.canvas = document.createElement('div');
        this.canvas.className = "panoramaCanvas";
        this.canvas.style.cursor = experience.panorama.getGrabCursor();
		this.positionCanvas(this.Params.RenderIn != null);

        // A queue for childern to be added to the canvas
        var childernQueue = [];

        var zoomInIcon = document.createElement('img');
        zoomInIcon.className = 'panoramaZoomInIcon';
        zoomInIcon.setAttribute('id','zoomInIcon');
		zoomInIcon.src = this.getImageResource('zoom_in'+cssType);
        //zoomInIcon.title = zoomInIcon.alt = experience.tr("Zoom In", experience.panorama.Locales);
        Event.observe(zoomInIcon, 'click', 
                experience.panorama.zoom.bindAsEventListener(this, experience.panorama.ZOOM_IN));
        zoomin = document.getElementById('ZoomIn');
        if (zoomin.childNodes.length==0)
			zoomin.appendChild(zoomInIcon);
		else
		{
			zoomin.removeChild(zoomin.firstChild);
			zoomin.appendChild(zoomInIcon);
		}
		
		//childernQueue.push(zoomInIcon);
      
        var zoomOutIcon = document.createElement('img');
        zoomOutIcon.className = 'panoramaZoomOutIcon';
		zoomOutIcon.setAttribute('id','zoomOutIcon');
        zoomOutIcon.src = this.getImageResource('zoom_out_disabled');
        //zoomOutIcon.title = zoomOutIcon.alt = experience.tr("Zoom Out", experience.panorama.Locales);
        Event.observe(zoomOutIcon, 'click', 
                experience.panorama.zoom.bindAsEventListener(this, experience.panorama.ZOOM_OUT));
        zoomout = document.getElementById('ZoomOut');
        if (zoomout.childNodes.length==0)
			zoomout.appendChild(zoomOutIcon);
		else
		{
			zoomout.removeChild(zoomout.firstChild);
			zoomout.appendChild(zoomOutIcon);
		}
		//childernQueue.push(zoomOutIcon);
        
        if (this.Params.ShowNavigator){

            var goDownIcon = document.createElement('img');
            goDownIcon.className = 'panoramaGoDownIcon';
            goDownIcon.src = this.getImageResource('go_down');
            goDownIcon.title = goDownIcon.alt =  
                experience.tr("Scrolling .. ", experience.panorama.Locales);
            Event.observe(goDownIcon, 'mouseover', 
                experience.panorama.move.bindAsEventListener(this, 
                    this.Params.ReverseScrolling? experience.panorama.MOVE_UP : experience.panorama.MOVE_DOWN));
            Event.observe(goDownIcon, 'mouseout', 
                experience.panorama.clearMoveTimeout.bindAsEventListener(this));
            childernQueue.push(goDownIcon);
            
            var goUpIcon = document.createElement('img');
            goUpIcon.className = 'panoramaGoUpIcon';
            goUpIcon.src = this.getImageResource('go_up');
            goUpIcon.title = goUpIcon.alt = 
                experience.tr("Scrolling .. ", experience.panorama.Locales);
            Event.observe(goUpIcon, 'mouseover', 
                experience.panorama.move.bindAsEventListener(this, 
                    this.Params.ReverseScrolling? experience.panorama.MOVE_DOWN : experience.panorama.MOVE_UP));
            Event.observe(goUpIcon, 'mouseout', 
                experience.panorama.clearMoveTimeout.bindAsEventListener(this));
            childernQueue.push(goUpIcon);
            

            var goRightIcon = document.createElement('img');
            goRightIcon.className = 'panoramaGoRightIcon';
            goRightIcon.src = this.getImageResource('go_right');
            goRightIcon.title = goRightIcon.alt = experience.tr("Scrolling .. ", experience.panorama.Locales);
            Event.observe(goRightIcon, 'mouseover', experience.panorama.move.bindAsEventListener(this, 
                    this.Params.ReverseScrolling? experience.panorama.MOVE_LEFT : experience.panorama.MOVE_RIGHT));
            Event.observe(goRightIcon, 'mouseout', 
                    experience.panorama.clearMoveTimeout.bindAsEventListener(this));
            childernQueue.push(goRightIcon);
            

            var goLeftIcon = document.createElement('img');
            goLeftIcon.className = 'panoramaGoLeftIcon';
            goLeftIcon.src = this.getImageResource('go_left');
            goLeftIcon.title = goLeftIcon.alt =  
                    experience.tr("Scrolling .. ", experience.panorama.Locales);
            Event.observe(goLeftIcon, 'mouseover', 
                    experience.panorama.move.bindAsEventListener(this, 
                        this.Params.ReverseScrolling? experience.panorama.MOVE_RIGHT : experience.panorama.LEFT));
            Event.observe(goLeftIcon, 'mouseout', 
                    experience.panorama.clearMoveTimeout.bindAsEventListener(this));
            childernQueue.push(goLeftIcon);
        }
        
        if (this.Params.ShowZoomSelectBox){
            var zoomDropDown = document.createElement('select');
            zoomDropDown.className = 'panoramaZoomDropdown';
            
			var zoomPercentages = new Array();
			var start = 100;
			var end = 300;
			var inc = 100;
			while(start<=end){
				zoomPercentages.push(start);
				start += inc;
			}

			this.Params.Controller.setZoomArray(zoomPercentages);
			this.Params.Controller.setZoomDropDown(zoomDropDown);
            for(var x = 0; x < zoomPercentages.length; x++){
                var opt = document.createElement('option');
                opt.innerHTML = zoomPercentages[x]+" %";
                opt.value = zoomPercentages[x];
				if(zoomPercentages[x]==100){
					experience.panorama.ZOOM_RESTORE_SIZE = x;
					opt.selected = true;
				}
                zoomDropDown.appendChild(opt);
            }
            Event.observe(zoomDropDown, 'change', 
                experience.panorama.handleZoomPercentageChange.bindAsEventListener(this));
            //childernQueue.push(zoomDropDown);
        }

        if (this.Params.ShowStatus){
            this.status = document.createElement('span');
            this.status.className = "panoramaStatus";
            childernQueue.push(this.status);
            this.setStatus(null, "<img src='" + this.getImageResource('loading') + "' />");
        }
        this.image = document.createElement('img');
        this.image.className = "panoramaImage";
        this.image.src = this.Params.ImageURL;
        //this.image.alt = this.Params.ImageURL;
        this.image.style.position = "relative";
		this.image.style.width  = this.Params.ImageWidth + "px";
        this.image.style.height = this.Params.ImageHeight + "px";
		
		this.positionImage();
        childernQueue.push(this.image);
        
        Event.observe(this.image, 'load', experience.panorama.setStatus.bindAsEventListener(this, ""));
        Event.observe(this.image, 'error', 
                        experience.panorama.setStatus.bindAsEventListener(this, 
                                experience.tr("Could not load image.", experience.panorama.Locales)));

        // Misc. handlers ..
        Event.observe(this.canvas, 'mousedown', 
                experience.panorama.handleMouseDown.bindAsEventListener(this));
        Event.observe(this.canvas, 'mousemove', 
                experience.panorama.handleMouseMove.bindAsEventListener(this));
        Event.observe(document, 'mouseup', 
                experience.panorama.handleMouseUp.bindAsEventListener(this));

        var wheelHandler = experience.panorama.handleMouseWheel.bindAsEventListener(this);
        Event.observe(this.canvas, "DOMMouseScroll", wheelHandler, false); // Mozilla
        Event.observe(this.canvas, "mousewheel", wheelHandler, false);

        // add elements to the canvas (in reverse for proper z-Index ordering)
        for(var i = childernQueue.length - 1; i >= 0; i--){
            this.canvas.appendChild(childernQueue[i]);
        } 
        
    },

    //// PUBLIC METHODS ///////////////////////////////////////////////////////    

    show : function(){
        if(!this.Params.RenderIn){
            this.fireListeners(this.onFullWindowListeners);
        }

        this.canvas.style.visibility = 'visible';
    },

    hide : function(){
        if(!this.Params.RenderIn){
            this.fireListeners(this.onUnFullWindowListeners);
        }

        this.canvas.style.visibility = 'hidden';
    },

    toggleFullWindow : function(e){
        //experience.Console.log(this.isMaximizedInstance);

        if (this.isMaximizedInstance){ // minimize
            this.closeImg.src = this.getImageResource('go_fullwindow');
            this.closeImg.title = this.closeImg.alt = experience.tr("Go Full-Window", experience.panorama.Locales);

            this.positionCanvas(true);
            this.isMaximizedInstance = false;
        } else { // maximize
            this.closeImg.src = this.getImageResource('unfullwindow');
            this.closeImg.title = this.closeImg.alt = experience.tr("Restore", experience.panorama.Locales);

            this.positionCanvas(false);
            this.isMaximizedInstance = true;
        }
    },

    getImage : function (){
        return [this.Params.ImageURL, this.Params.ImageWidth, this.Params.ImageHeight];
    },

    setImage : function(url, width, height){
		this.setStatus(null, "<img src='" + this.getImageResource('loading') + "' />");
        this.image.src = this.Params.ImageURL = sonurl;
		this.image.style.width = this.Params.ImageWidth  = width + "px";
        this.image.style.height = this.Params.ImageHeight = height + "px";
    },

    addOnFullWindowListener : function(listener){
        this.onFullWindowListeners[this.onFullWindowListeners.length] = listener;
    },

    removeOnFullWindowListener : function(listener){
        if (this.onFullWindowListeners.include(listener)){
            this.onFullWindowListeners.splice(this.onFullWindowListeners.indexOf(listener), 1);
        }
    },

    addOnUnFullWindowListener : function(listener){
        this.onUnFullWindowListeners[this.onUnFullWindowListeners.length] = listener;
    },

    removeOnUnFullWindowListener : function(listener){
        if (this.onUnFullWindowListeners.include(listener)){
            this.onUnFullWindowListeners.splice(this.onUnFullWindowListeners.indexOf(listener), 1);
        }
    },

    //// PRIVATE METHODS ///////////////////////////////////////////////////////

    fireListeners : function(listeners){
        for(var i =0; i < listeners.length; i++){
            listeners[i]();
        }
    }, 

    setStatus : function(e, html){
		Log.debug("setStatus!"+html);
        if (this.Params.ShowStatus){
            this.status.innerHTML = html;
        }
    },

    showHelp : function(e){
        alert(experience.tr("HelpText", experience.panorama.Locales));
    },

	restoreImagePosition : function(){
		this.positionImage();
	},

    positionImage :  function (e){
        var image = this.image;
        // detecting canvas width and height doesn't work in KHTML (and WebKit?)
        /*if (experience.detectEngine() == "khtml"){
            image.style.top = image.style.left = this.Params.InnerUpperOffset + "px";
            return;
        }*/

        var canvasWidth  = this.Params.CanvasWidth;
        var canvasHeight = this.Params.CanvasHeight;
		if(image.style.width>canvasWidth){
			image.style.left =  ((canvasWidth - parseFloat(image.style.width)) / 2) + "px";
		}else{
			image.style.left =  ((canvasWidth - parseFloat(image.style.width)) / 2) + "px";
		}
		image.style.top =  ((canvasHeight - parseFloat(image.style.height)) / 2) + "px";
		
    },

    positionCanvas : function (isRenderIn){

        if(this.canvas.parentNode){
            this.canvas.parentNode.removeChild(this.canvas);
        }

        if(isRenderIn){
            if(this.isMaximizedInstance){
                this.fireListeners(this.onUnFullWindowListeners);
            }

            $(this.Params.RenderIn).style.position = "relative";
            this.canvas.style.position = "absolute";
            this.canvas.style.left = 
                this.canvas.style.right =
                this.canvas.style.top = 
                this.canvas.style.bottom = "0px";
            this.canvas.style.height = this.canvas.style.width = "100%";
            this.canvas.style.visibility  = 'visible';

            $(this.Params.RenderIn).appendChild(this.canvas);
        } else {
            if(this.Params.RenderIn){
                this.fireListeners(this.onFullWindowListeners);
            }

            document.getElementsByTagName('body')[0].appendChild(this.canvas);

            if (experience.detectBrowser() == "ie5" || experience.detectBrowser() == "ie6"){
                this.canvas.style.position = "absolute";
                this.canvas.style.setExpression("top", 
                    "(ignoreMe = document.documentElement.scrollTop? " + 
                        "document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
                this.canvas.style.setExpression("height",
                     "experience.panorama.getInnerWindowDimensions()['height']");
                this.canvas.style.setExpression("width",
                     "experience.panorama.getInnerWindowDimensions()['width']");
            } else {
                this.canvas.style.position = "fixed"
            }
        }

        //experience.Console.log(this.canvas.parentNode.tagName + "," + isRenderIn);
    },

    /**
      * Thanks to http://www.quirksmode.org/viewport/compatibility.html 
      */
    getInnerWindowDimensions: function (){
        var x,y;
        if (self.innerHeight) // all except Explorer
        {
            x = self.innerWidth;
            y = self.innerHeight;
        }
        else if (document.documentElement && document.documentElement.clientHeight)
            // Explorer 6 Strict Mode
        {
            x = document.documentElement.clientWidth;
            y = document.documentElement.clientHeight;
        }
        else if (document.body) // other Explorers
        {
            x = document.body.clientWidth;
            y = document.body.clientHeight;
        }

        return {width: x, height: y};
    },

	restoreZoom : function(e, index){
		var c = this.Params.Controller;
		c.doZoom(index);
	},

    zoom : function(e, delta){
		var c = this.Params.Controller;
		var index = c.getZoomIndex(delta);
		c.doZoom(index);
    },

    move : function (e, toWhere){
        if (!this.isBeingDragged){
            var MOVE_BY = this.Params.MoveBy;
    
            switch(toWhere){
                case experience.panorama.MOVE_DOWN:
                    this.image.style.top = (parseFloat(this.image.style.top) + MOVE_BY) + "px";
                    break;
                case experience.panorama.MOVE_UP:
                    this.image.style.top = (parseFloat(this.image.style.top) - MOVE_BY) + "px";
                    break;
                case experience.panorama.MOVE_RIGHT:
                    this.image.style.left = (parseFloat(this.image.style.left) + MOVE_BY) + "px";
                    break;
                case experience.panorama.MOVE_LEFT:
                    this.image.style.left = (parseFloat(this.image.style.left) - MOVE_BY) + "px";
                    break;
                default:
                    experience.Console.log("Unrecognized 'toWhere' value '" + toWhere + "'");
                    return;
            }
    
            this.timeOutId = 
                setTimeout(experience.panorama.move.bind(this, null, toWhere), this.Params.MoveRate);
        }
    },

    clearMoveTimeout : function (e){
         clearTimeout(this.timeOutId);
    },

	doZoom:function(el, index, percentage){
		this.Params.Controller.setZoom(percentage);
		percentage = percentage/100;
		if (percentage != '#'){
            var newWidth, newHeight, newLeft, newTop;

            var c = this.Params.Controller;
			if (percentage==3){percentage=4;}
			newWidth  = c.getOriginalWidth() * percentage;
            newHeight = c.getOriginalHeight() * percentage;
			
			var sayiurl,sonurl;
			sonurl = c.getURL();
			if (index>0 && index <=1)
			{
				sayiurl = c.getURL();
				sayiurl = sayiurl.substring(sayiurl.length-5, sayiurl.length-4);
				sayiurl --;
				sonurl = c.getURL();
				sonurl = sonurl.substring(0, sonurl.length-5);
				sonurl += sayiurl + ".jpg";
			}
			if (index>1 && index <=2)
			{
				sayiurl = c.getURL();
				sayiurl = sayiurl.substring(sayiurl.length-5, sayiurl.length-4);
				sayiurl = sayiurl - 2; 
				sonurl = c.getURL();
				sonurl = sonurl.substring(0, sonurl.length-5);
				sonurl += sayiurl + ".jpg";
			}
			this.image.src = this.Params.ImageURL = sonurl;

			zoomout = document.getElementById('zoomOutIcon');
			if (index == 0) zoomout.src = this.getImageResource('zoom_out_disabled');
			else zoomout.src = this.getImageResource('zoom_out'+cssType);
			zoomin = document.getElementById('zoomInIcon');
			if (index == 2) zoomin.src = this.getImageResource('zoom_in_disabled')
			else zoomin.src = this.getImageResource('zoom_in'+cssType);

            // distribute size change
			if(newWidth>this.Params.CanvasWidth){
				newLeft = parseFloat(this.image.style.left) - 
								((newWidth - parseFloat(this.image.style.width)) / 2);
			}else{
				newLeft = (this.Params.CanvasWidth - newWidth) / 2;
			}
			if(newHeight>this.Params.CanvasHeight){
				newTop  = parseFloat(this.image.style.top) - 
								((newHeight - parseFloat(this.image.style.height)) / 2); 
			}else{
				newTop  = (this.Params.CanvasHeight - newHeight) / 2;
			}
            
            // apply new size
            this.image.style.width  = newWidth  + "px";
            this.image.style.height = newHeight + "px";

            this.image.style.left   = newLeft   + "px";
            this.image.style.top    = newTop    + "px";
            el.selectedIndex = index;

			var me = this;
			c.wait(function(){
				c.setSize(parseInt(newWidth),parseInt(newHeight));
				me.setImage(sonurl, c.getWidth(), c.getHeight());
			});
        }
	},
	
    handleZoomPercentageChange : function(e){
		var percentage = Event.element(e).value;
		this.Params.Controller.doZoom(this.Params.Controller.getIndex(percentage));
    },

    handleMouseDown : function(e){
        if (
            (
                Event.element(e) == this.canvas ||
                Event.element(e) == this.image
            ) && Event.isLeftClick(e)
           ){

            this.isBeingDragged = true;
            this.canvas.style.cursor = experience.panorama.getGrabbingCursor();
            this.lastLeft = parseFloat(this.image.style.left);
            this.lastTop  = parseFloat(this.image.style.top);
            this.lastX = Event.pointerX(e);
            this.lastY = Event.pointerY(e);
            
            // I love Prototype!
            Event.stop(e);
        }
    },

    handleMouseMove : function (e){
        if (
            Event.element(e) == this.canvas ||
            Event.element(e) == this.image
           ){
                var sign = this.Params.ReversePanning? -1 : 1;
                if (this.isBeingDragged){
                    this.image.style.left =  this.lastLeft + (sign * (Event.pointerX(e) - this.lastX)) + "px"; 
                    this.image.style.top  =  this.lastTop  + (sign * (Event.pointerY(e) - this.lastY)) + "px"; 
                }
                
                Event.stop(e);
        }
    },

    handleMouseUp : function(e){
        this.isBeingDragged = false;
        this.canvas.style.cursor = experience.panorama.getGrabCursor();
    },

    getGrabCursor : function(e) {
        if(experience.detectEngine() == "gecko"){
            return '-moz-grab';
        } else {
            return 'move';
        }
    },

    getGrabbingCursor : function(e){
		if(experience.detectEngine() == "gecko"){
            return '-moz-grabbing';
        } else {
            return 'move';
        }
    },

    handleMouseWheel: function(event){
        var delta = 0;

        if (event.wheelDelta) { // IE/Opera. 
            delta = event.wheelDelta/120;
            //In Opera 9, delta differs in sign as compared to IE.
            if (window.opera)
                delta = -delta;
        } else if (event.detail) { // Mozilla case. 
                // In Mozilla, sign of delta is different than in IE.
                // Also, delta is multiple of 3.
                delta = -event.detail/3;
        }

        delta = Math.round(delta); //Safari Round

        if (delta){
                experience.panorama.zoom.bindAsEventListener(this, delta)();
        }

        Event.stop(event);
    },

    getImageResource : function (resource){
            return this.Params.IconDirectory + "/" + resource  
                                        + this.Params.IconExtension;
    },


    Locales : $H({
        'en_US' : {
            'HelpText' : "Grab (click and drag) the image to move it around. Use your mouse wheel to zoom in and out the image or, if you don't have one, use the zoom icons in the toolbar. If you hover with your mouse pointer over any of the navigator arrow in the bottom right corner, the image will starting moving in that direction (automatic scrolling.)\n\nPanorama is part of the Experience JavaScript Library.\nFor details, see project website at http://experience.sf.net\n"
        },

        'ar' : {
            'Zoom In' : '?????',
            'Zoom Out' : '?????',
            'Restore Original Size' : '??????? ????? ??????',
            'Restore Original Position' : '??????? ?????? ??????',
            'Close' : '?????',
            'Scrolling .. ' : '???? ??????? ...',
            'Help': '??????',
            'HelpText' :  '???? (???? ? ??) ?????? ?? ??????. ?????? ???? ?????? ?????? ?? ????? ??????. ??? ?? ??? ???? ?????? ??????? ????????? ???? ??? ???? ???????. ??? ???? ???? ?????? ??? ???? ???? ?????? ?? ?????? ?????? ??????? ???? ????? ?????? ?? ?? ??? ??????? (????? ??????). \n\n ???????? ?? ??? ?? ????? ???????? ???????? ??????????. \n ????? ?? ????????? ???? ????? ???? ??????? ?? \n http://experience.sf.net',
            'Could not load image' : '??? ????? ????? ??????'
            ,'Go Full-Window' : '???? ??????? ???????',
            'Restore' : '???????'
        }
    })
}


