
/*************************************************************************************************************************
 *  Details area class
 *  
 *  IMPRV: refactor anything below and clean up nomenclature 
 *************************************************************************************************************************/
var DetailsArea = new Class({
		bolVisible: false, // holds the current visibility state of the element
        bolZoomed: false,
        bolZooming: false,
		idDetailsArea: null, // the wrapper
		idDetailsAreaCanvas: null, // the canvas
		urlPromotionsSource: '', // stores the current url displayed/loaded
		idPromotions: null, // the Promotions 
		dragPromotions: undefined, // hold a reference to the Drag fx instance
		objDragLimit: undefined, // the dragging limit coordinates are stored here
		idPromotionsWidth: function () { // el.getComputerSize.totalWidth fails to work for some reason
			var clsPromotion = this.idPromotions.getElements('.clsPromotion');
        	var width = 0;
			clsPromotion.each(
        			function(item, index) {
        				width += item.getComputedSize().totalWidth; 
        			}.bind(this)
        	); // end clsPromotion.each
			return width;
		},
		numPromoSizeStartFactor: 0.9, // the promo will fill 90% of height of screen 
		Implements: [Options, Events],
        options: {
        	urlPromotionsSource: null,
        	idDetailsArea: null, // element NOT string
        	cssWidth: '80%'
        },
        initialize: function(options){
                var self = this;
        		this.setOptions(options);
                
                this.idDetailsArea = this.options.idDetailsArea.set('html', 
            			"<div id='idDetailsAreaCanvas'>" +
                		"<div id='idDetailsAreaControls'>" +
            				"<ul class='clsHorizontalNav'>" +
            				"<li><a id='idActionPrint' target='_blank' href='#'><img class='clsClickable' alt='Print' src='/static/template/icons/printer-icon.png'></a></li>" +
            					"<li><a id='idActionZoom' href='#'><img class='clsClickable clsLiClose' alt='Zoom Toggle' src='/static/template/icons/zoom-icon.png'></a></li>" +
            					"<li><a id='idActionClose' href='#'><img class='clsClickable clsLiClose' alt='Close' src='/static/template/icons/close-icon.png'></a></li>" +
            				"</ul>" +
            			"</div>" +
            			"<div id='idPromotions'>" +
            			"</div>" +
            			"</div>"
            	);
                this.idDetailsAreaCanvas = this.idDetailsArea.getElementById('idDetailsAreaCanvas');
                
                /************************************************************
                 * Set required styles dimensions 
                 ***********************************************************/
                this.idDetailsArea.setStyles({
                		position: 'absolute',
                		overflow: 'hidden',
                		'z-index': '0', //so we can click controls
                		width: this.options.cssWidth,
                		height: '100%',
                		right: '0px',
                		top: '0px'
                }),
                this.idDetailsAreaCanvas.setStyles({
                	position: 'relative',
                	top: '0px',
            		right: -1 * this.idDetailsArea.getSize().x,
            		width: '100%',
                	height: $(document).getSize().y
                });
                window.addEvent('resize', function () {
                	self.idDetailsAreaCanvas.setStyles({
                     	height: $(document).getSize().y
                     });
                	self.initCanvas();
                	self.initDraging();
                });
                
                
                /*************************************************************************************
                 * Load promotions if needed
                 *************************************************************************************/
                this.idPromotions = this.idDetailsArea.getElementById('idPromotions');
                if (this.options.urlPromotionsSource) {
                	this.addPromotions(this.options.urlPromotionsSource);
                	this.toggleVisibility();
                }
                
                /*************************************************************************************
                 * Add button actions and other events
                 *************************************************************************************/
                // *** Draging fx is very dynamic and is always re-initilized though this.addPromotions() *** //
                
                this.idDetailsArea.getElement('#idActionClose').addEvent('click', function() {
                	this.toggleVisibility();
                }.bind(this));
                
                this.idDetailsArea.getElement('#idActionZoom').addEvent('click', function() {
                	this.toggleZoom();
                }.bind(this));
                
                this.idPromotions.addEvent('mousewheel', function(event) {
                	var event = new Event(event);
                	/* Mouse wheel UP */
                	var zoomFactor; 
                	if (event.wheel > 0) {
                		this.promotionsToHeight(this.idPromotions.getSize().y*1.10);
                	}
                	else if (event.wheel < 0) {
                		this.promotionsToHeight(this.idPromotions.getSize().y*.90);
                	}
                }.bind(this));
        
               
        },
        
        /********************************************************************************
         * Loads new promos from a http url
         * 
         * IMPRV: add a loading progress bar indicator when waiting for flyers to load
         ********************************************************************************/
        addPromotions: function(url) {
        	
        	this.idPromotions.tween('opacity', 0);
        	var objHTMLRequest = new Request.HTML({
	        		url: url,
	        		onSuccess: function(responseTree, responseElements, responseHTML) {
	        			// IMPRV: this hack uses Assets.images() to fire functions AFTER they accutally are laoded
	        			// Request.HTML onSuccess: fires before the rendering is done
	        			var arrUrls = []
	        			responseElements.each(function(item, index) {
	        				if (item.get('tag') == 'img') {
	        						arrUrls.push(item.getProperty('src'));
	        				}
	        			});
	        			//trace(JSON.stringify(arrUrls));
	        			Asset.images(arrUrls, {
	        				onComplete: function(){
	        					this.idPromotions.set('html', responseHTML);
	    	        			this.urlPromotionsSource = url;
	    	        			this.initCanvas();
	    	        			this.idPromotions.tween('opacity', 1);
	    	        			this.initDraging();
	    	        			this.initPrint(url);
	        			    }.bind(this)
	        			});

	        			}.bind(this)
	        }).get();
        },
        
        /********************************************************************************
         * Hides or shows the details area
         ********************************************************************************/
        toggleVisibility: function() {
        	var fxTween = new Fx.Tween(this.idDetailsAreaCanvas);
        	if (this.bolVisible) {
        		this.bolVisible = false;
        		fxTween.start('right', -1 * this.idDetailsArea.getSize().x).chain(
        				function () { this.idDetailsArea.setStyle('z-index', '0') }.bind(this) // so we can click controls on map
        		); //slide out
        	}
        	else {
        		this.bolVisible = true;
        		this.idDetailsArea.setStyle('z-index', '100');
        		//this.initCanvas();
        		fxTween.start('right', 0);
        	}
        },
        
        /********************************************************************************
         * Zoomed in and zoomed out mode.
         * 
         * IMPRV: add a check if currently zooming than not to execute - as quick succession makes it brake
         ********************************************************************************/
        toggleZoom: function() {
        	//zoom out
        	if (this.bolZoomed) {
        		this.promotionsToHeight(this.idDetailsArea.getSize().y * this.numPromoSizeStartFactor);
        		this.bolZoomed = false;
        	
        	}
        	else {
        		this.promotionsToHeight(this.idDetailsArea.getSize().y * this.numPromoSizeStartFactor * 1.5);
				this.bolZoomed = true;
        	}
        },
        
        /*****************************************************************************************
         * Resizes promotionsToHeight and pans to optional coordinates
         * 
         * IMPRV: Clean and improve the zooming function!!!
         *****************************************************************************************/
        promotionsToHeight: function(numNewHeight, objPanTo) {
        	// exit if we are already zooming
        	if (this.bolZooming == true) {
        		return false;
        	}
        	this.bolZooming = true;
        	
        	var numOldHeight = this.idPromotions.getSize().y;
        	var numOldWidth = this.idDetailsAreaCanvas.getElement('.clsPromotion').getSize().x;
        	var numNewWidth = numOldWidth * (numNewHeight / numOldHeight);
        	
        	
        	
        	// center of canvas
        	var objPanCenter = {x: this.idDetailsArea.getCoordinates().width/2+this.idDetailsArea.getCoordinates().left, 
					   		 y: this.idDetailsArea.getCoordinates().height/2+this.idDetailsArea.getCoordinates().top
					   		};
        	//trace('objPanCenter: ' + JSON.stringify(objPanCenter));
        	
        	// if pan to not specified than zoom in on center
        	if (objPanTo == undefined) {
        		var objPanTo = objPanCenter;
        	}
        	//trace('objPanTo: ' + JSON.stringify(objPanTo));
        	var objPanToCalculated = { // adjust the pan based on resize factor
        			x: ((objPanTo.x - objPanCenter.x) + ((numOldWidth - numNewWidth)/2)),
        			y: ((objPanTo.y - objPanCenter.y) + ((numOldHeight - numNewHeight)/2))
        	};
        	//trace('objPanToCalculated: ' + JSON.stringify(objPanToCalculated));
        	
        	// now we need to take drag limits into consideration when panning AND if the element should be center as it just fits on screen
        	var numPanLeft =  this.idPromotions.getPosition(this.idDetailsAreaCanvas).x  * numNewHeight / numOldHeight + objPanToCalculated.x;
        	var numPanTop =  this.idPromotions.getPosition(this.idDetailsAreaCanvas).y  * numNewHeight / numOldHeight + objPanToCalculated.y;
        	var numNewPromoWidth = this.idPromotionsWidth() * numNewHeight / numOldHeight;
        	var objDragLimit = this.getDragingLimit(numNewPromoWidth, numNewHeight);
        	
        	if (numNewPromoWidth > this.idDetailsAreaCanvas.getSize().x) { // if width bigger than canvas
	        	if (numPanLeft < objDragLimit.x[0]) { // promos are to much to the left
	        		numPanLeft = objDragLimit.x[0];
	        		//trace('numPanLeft: ' + numPanLeft);
	        	} 
	        	else if (numPanLeft > objDragLimit.x[1]) { // promos to much to the right
	        		numPanLeft = objDragLimit.x[1];
	        		
	        	}
        	}
        	else { // center horizontally
        		numPanLeft = (this.idDetailsAreaCanvas.getSize().x - numNewPromoWidth)/2;
        	}
        	
        	if (numNewHeight > this.idDetailsAreaCanvas.getSize().y) { // hight bigger than canvas
	        	if (numPanTop < objDragLimit.y[0]) { // promos are to much to the top
	        		numPanTop = objDragLimit.y[0];
	        	} 
	        	else if (numPanTop > objDragLimit.y[1]) { // promos to much down
	        		numPanTop = objDragLimit.y[1];
	        	}
        	}
        	else { // center vertically
        		numPanTop = (this.idDetailsAreaCanvas.getSize().y - numNewHeight)/2;
        	}
        	//trace('numPanLeft: ' + numPanLeft + ', numPanTop: ' + numPanTop);
        	
        	// pan it
        	this.idPromotions.morph(
            		{
            		'left': numPanLeft,
            		'top': numPanTop
            		}
            );
        	
        	
        	// prepare the resize FXs
        	var newImgHeight; // holds last 
        	var arrPromotions = this.idPromotions.getElements('.clsPromotion');
        	var objFxOptions = {}; // this holds the individual fx properties for each img we are resizing
        	arrPromotions.each(
        			function(item, index) {
        				var img = item.getElement('img');
        				newImgHeight = numNewHeight - item.getElement('.clsPromotionHeader').getSize().y - item.getStyle('border-top-width').toInt() - item.getStyle('border-bottom-width').toInt();
        				objFxOptions[index] = {'height': [img.getSize().y, newImgHeight]};
        			}.bind(this)
        	); // end clsPromotion.each
        	
        	// resize it 
        	var fxElements = new Fx.Elements(this.idPromotions.getElements('.clsPromotion img'), {
        			onComplete: function() {
        				this.initDraging(), // when we call initDragging from here than this must be binded to whole class
        				this.bolZooming = false;
        			}.bind(this)
        	}).start(objFxOptions);
        },

        /********************************************************************************
         * returns the drag limits - {x: [numMin, numMax], y: [numMin, numMax]}
         * 
         * takes optional numPromosWidth, numPromosHeight - useful if you wish to predict
         * the drag limit
         ********************************************************************************/
        getDragingLimit: function (numPromosWidth, numPromosHeight) {
	        //trace('getDragingLimit');
	    	// based on the current idPromotions width and height we calculate the
	    	// Drag's dragging limits 
	    	var numPromosWidth = numPromosWidth || this.idPromotionsWidth();
	    	var numPromosHeight = numPromosHeight || this.idPromotions.getSize().y;
	    	
	    	// horizontal limits
	    	if (numPromosWidth <= this.idDetailsArea.getSize().x) {
	    		xDragLimit = [this.idPromotions.getPosition(this.idDetailsAreaCanvas).x, this.idPromotions.getPosition(this.idDetailsAreaCanvas).x];
	    	}
	    	else {
	    		xDragLimit = [- (numPromosWidth - this.idDetailsArea.getSize().x + 14),
	    		              14]; 
	    	}
	    	// vertical limits
	    	if (numPromosHeight <= this.idDetailsArea.getSize().y) {
	    		yDragLimit = [this.idPromotions.getPosition(this.idDetailsAreaCanvas).y, this.idPromotions.getPosition(this.idDetailsAreaCanvas).y];
	    	}
	    	else {
	    		yDragLimit = [ - (numPromosHeight - this.idDetailsArea.getSize().y + 14 ),
	    		               14
	    		               ]
	    	}
	    	
	    	// assamble the drag limits
	    	var objDragLimits = { 
	    			x: xDragLimit, 
	    			y: yDragLimit
	    	};
	    	//trace(JSON.stringify(objDragLimits));
	    	
	    	return objDragLimits;
        },
        /********************************************************************************
         * Initialises/re-initialises dragging FX to the idPromotions and limits it as 
         * needed based on width and height. Call this after any changes to promotion display 
         ********************************************************************************/
        initDraging: function () {
        	var self = this;
        	var idDragPromotions = $('idPromotions');
        	var dragPromotions = new Touch(idDragPromotions);
	    	var dragLimit = self.getDragingLimit();
	    	var curPosition = {
	    		top: undefined,
	    		left: undefined
	    	};
	    	
	    	dragPromotions.addEvent('start', function(dx, dy) {
	    		curPosition = {
	    	    		top: idDragPromotions.getStyle('top').toInt(),
	    	    		left: idDragPromotions.getStyle('left').toInt()
	    	    }
	    	});
	    	
	    	//trace(JSON.stringify(curPosition));
	    	dragPromotions.addEvent('move', function(dx, dy) {
	    		
	    		var newPosition = {
	    				top: Math.min(dragLimit.y[1], Math.max(curPosition.top + dy, dragLimit.y[0])),
	    				left: Math.min(dragLimit.x[1], Math.max(curPosition.left + dx, dragLimit.x[0]))
	    		}
	    		idDragPromotions.setStyles({
	    				top: newPosition.top,
	    				left: newPosition.left
	    				});
	    	});
	    	
        	
        	// FIXME: rather than detach update the old Drag handle
        	//if (this.dragPromotions != undefined) {
        	//	this.dragPromotions.detach();
        	//}
        	//this.dragPromotions = new Drag($('idPromotions'), {
	        //		limit: this.getDragingLimit(),
	        //    	snap: 0,
	        //		preventDefault: true
	        //});
        	
        },
        
        
        /********************************************************************************
         * This function resizes and centers promotions that are currently loaded, should 
         * be always called after new promotions are loaded
         ********************************************************************************/
        initCanvas: function () {
        	//trace('initCanvas');
        	var numNewHeight = this.idDetailsArea.getSize().y * this.numPromoSizeStartFactor;
        	// resize to default size
        	var clsPromotion = this.idPromotions.getElements('.clsPromotion');
        	// IMPRV: factor below out and call this.promotionsToHeight
        	clsPromotion.each(
        			function(item, index) {
        				var img = item.getElement('img');
        				var newImgHeight = numNewHeight - item.getElement('.clsPromotionHeader').getSize().y - item.getStyle('border-top-width').toInt() - item.getStyle('border-bottom-width').toInt();
        				img.setStyle('height', newImgHeight);
        				item.setStyle('text-align', 'center'); //IMPRV: move this into css sheet
        			}.bind(this)
        	); // end clsPromotion.each
        	this.bolZoomed = false;
        	
        	// center horizontally if needed
        	if (this.idPromotionsWidth() < this.idDetailsAreaCanvas.getSize().x) {
        		numLeftOffset = (this.idDetailsAreaCanvas.getSize().x - this.idPromotionsWidth())/2;
        		this.idPromotions.setStyle('left', numLeftOffset);
        	}
        	else {
        		this.idPromotions.setStyle('left', 14);
        	}
        	// center vertically
        	this.idPromotions.setStyle('top', (this.idDetailsAreaCanvas.getSize().y - this.idPromotions.getSize().y)/2);

        	
        },
        
        initPrint: function (url) {
        	var idActionPrint = this.idDetailsArea.getElement('#idActionPrint');
        	idActionPrint.set('href', url.match(/.+\//) + '?print=True');
        	
        }

});
/*
 window.addEvent('lozad', function () {
	// register the global variables
	var idDetailsArea = $('idDetailsArea');
	var clsPromotion = $$('#idPromotions .clsPromotion');
	var idPromotions = $('idPromotions');
	
	// CSS hacks/prep
	var idPromotionsWidth = idPromotions.getStyle('width').toInt(); 											// since mootools operates the fx on inline el styles so
	var idDetailsAreaWidth = idDetailsArea.getStyle('width').toInt(); 											// the first tween run defaults to px rather than % as it is
	idPromotions.setStyle('width', (idPromotionsWidth/idDetailsAreaWidth*100).round() + '%');   		// missing from inline style so we need to manually set it
	idPromotions.set('tween', {unit: '%'}); //since all of our design is in % we need to use that as default
	
	// find the center point of the details area 
	var idDetailsAreaHeight =idDetailsArea.getStyle('height').toInt();
	var idDetailsAreaWidth = idDetailsArea.getStyle('width').toInt();
	var idDetailsAreaCenter = {x: (idDetailsAreaWidth/2).round()+ idPromotions.getPosition().x, y: (idDetailsAreaHeight/2).round()}; 
	
	//console.log('idDetailsAreaCenter: ' + JSON.stringify(idDetailsAreaCenter));

	// add wheel zoom
	idDetailsArea.addEvent('mousewheel', function(event) {
		// Initalize stuff - we must work in pixels for saftey accross all browsers
		var zoomIncrement = 10; //increment to 'zoom' by changing the width by n units (in %)
		var zoomWeighter = 0.7; // softening the acctuall panning during zoom
		var currentZoom = idPromotions.getStyle('width').toInt(); // grab the current width 
		//console.log('currentZoom: ' + currentZoom);
		var zoomOffset = {x: 0, y:0} 	//compensates for width changes when zooming in or out
												// the % are consecutive i.e. width * (5% + 5% + 5%) = width * 5% + width * 5% + width * 5%
												// so we only need to grab width * 5% once since we are panning left and top during zoom by adding the zoomoffset
		
		//console.log('idPromotions.getSize(): ' + JSON.stringify(idPromotions.getSize()));
		//console.log('idPromotions.getSize().x * (1+  zoomIncrement/100): ' + idPromotions.getSize().x * (1 + zoomIncrement/100));
		
		var zoomIncrementP =  1 + zoomIncrement/100;
		//console.log('zoomIncrementP: ' + zoomIncrementP);
		
		zoomOffset.x = Math.abs((idPromotions.getSize().x - (idPromotions.getSize().x*zoomIncrementP))/2);
		zoomOffset.y = Math.abs((idPromotions.getSize().y - (idPromotions.getSize().y*zoomIncrementP))/2);	
		//console.log('zoomOffset: ' + JSON.stringify(zoomOffset));
		
		 Mousewheel UP 
		if (event.wheel > 0) {
			idPromotions.morph({
				left: idPromotions.getStyle('left').toInt()-zoomOffset.x+(idDetailsAreaCenter.x-event.client.x)*zoomWeighter,
				top: idPromotions.getStyle('top').toInt()-zoomOffset.y+(idDetailsAreaCenter.y-event.client.y)*zoomWeighter
			}); // end panning function
			idPromotions.tween('width', currentZoom, currentZoom+zoomIncrement); // tween in %
		} 
		 Mousewheel DOWN
		else if (event.wheel < 0) {
			idPromotions.morph({
				left: idPromotions.getStyle('left').toInt()+zoomOffset.x+(idDetailsAreaCenter.x-event.client.x)*zoomWeighter,
				top: idPromotions.getStyle('top').toInt()+zoomOffset.y+(idDetailsAreaCenter.y-event.client.y)*zoomWeighter
			}); // end panning function
			idPromotions.tween('width', currentZoom, currentZoom-zoomIncrement); // tween in %
		}
	}); //zooming functionatily end
	
	
});*/
