 /*
  * MDVMapSlider presumes
  * 
  * -	mdvLib.js
  */
  
   /*
  * MDVMapSlider
  * @constructor
  * @param 			mdvMap
  * @param			object literal to override default settings  (optional)
  */

function MDVMapSlider(mdvMap, options) {
	
	if (!mdvMap) {
 		return;
 	}
 	this.mdvMap = mdvMap;
 	
 	this.mdvMap.registerGadget(this);

 	for (var method in MDVGadgetBase.prototype) {
        if (!MDVMapSlider.prototype[method])
            MDVMapSlider.prototype[method] = MDVGadgetBase.prototype[method];
    }

 	this.name = 'MapSlider';
	
	this.imgs = {
		plus:		'zoom_Plus.png',
		minus:		'zoom_Minus.png',
		tick:		'zoom_tick.png',
		knob:		'drag_bar.png',
		indicator:	'sizableBar.png',
		bg:			'zoomBG.png'
	};
	

	this.sliderOffsetTop = 50;
	//this.sliderTotalHeight = 164;
	this.sliderOffsetLeft = 21;
	this.tickDiv = null;
	this.tickOffset = 18;
	this.tickOffsetLeft = 10;
	this.tickPositions = [];
	this.knob = null;
	this.knobDiv = null;
	this.knobActive = false;
	this.timer = null;
	this.timerDelay = 20;
	this.currentLevel = 0;
	this.zoomLevels = 0;
	this.indicator = null;
	this.imagePath = this.mdvMap.config.get('imagePath');
	this.imagePath += 'zoom/';
	this.imageRolloverPath = 'rollover/';
	this.plus = null;
	this.plusOver = null;
	this.minus = null;
	this.minusOver = null;
	this.bg = null;
	this.bgPos = 0;
	this.garbage = [];
	this.init = false;
    
    // text
    this.text = new Array();
    this.text['zoomIn'] = 'zoom in';
 	this.text['zoomOut'] = 'zoom out';
	
	//override defaults
	if (options !== null) {
		for(var setting in options) {
			if (this[setting]) {
				this[setting] = options[setting];
			}
		}	
	}
	// mdvMap already initialized?
	if (this.mdvMap.viewportRealWidth !== -1) {
		this._execute();
	// ...otherwise wait until map is ready
	} else {
		this.mdvMap.events.registerEvent(MDVEvent_MAP_INITIALISED, this, this._execute);
	}
}

MDVMapSlider.prototype.destroy = function() {

	// reset references, unhook events 
 	// marked for garbage collection
 	for(var i = 0, len = this.garbage.length; i < len; i++) {
 		var target = this.garbage[i];
 		switch (mdvLib.typeOf(target)) {
 			case 'string':	if (this[target]) {
 								this[target] = null;
 							} 
 							break; 
 			case 'object':	target = null;
 							break;
 			case 'array':	var obj = this.garbage[i][0];
 							var evt = this.garbage[i][1];
 							if(this[obj][evt]) {
 								this[obj][evt] = null;
 							}
 							break;
 			default:		break;	
 		}
 	}
};

MDVMapSlider.prototype.createContainer = function() {
	
	var divSlider		= createDiv('divSlider');
	var divSliderPlus	= createDiv('divSliderPlus');
	var divSliderBG		= createDiv('divSliderBG');
	var divSliderKnob	= createDiv('divSliderKnob');
	var divSliderTicks	= createDiv('divSliderTicks');
	var divSliderMinus	= createDiv('divSliderMinus');
		
	mdvLib.style([divSlider], {
		position: 'absolute',
		top: this.sliderOffsetTop + 'px',
		//top: (Math.floor(this.mdvMap.viewportHeight / 2) - (this.sliderTotalHeight / 2)) + 'px',
		left: this.sliderOffsetLeft + 'px',
		zIndex: 999 
	});
	
	mdvLib.style([divSliderPlus, divSliderMinus, divSliderBG], {
		position: 'relative'
	});
	
	mdvLib.style([divSliderPlus, divSliderMinus], {
		marginLeft: '3px',
		zIndex: 6,
		height: '18px',
		width: '18px'
	});
	
	divSliderPlus.onclick = function() { 
		
		if((this.currentLevel + 1) <= (this.zoomLevels - 1)) {
			this.setZoomLevel(this.getZoomLevel()+1);
		}
		this.clearTimer();
		this.animate.bind(this)();
		return false;
		
	}.bind(this);
	
	divSliderPlus.onmouseover = function() { 
		this.plus.style.left = '-2000px';
		this.plusOver.style.left = '0px';
	}.bind(this);
	
	divSliderPlus.onmouseout = function() {
		this.plus.style.left = '0px';
		this.plusOver.style.left = '-2000px';
	}.bind(this);
	
	divSliderMinus.onclick = function() { 
		
		if ((this.currentLevel - 1) >= 0) {
			this.setZoomLevel(this.getZoomLevel()-1);
		}
		this.clearTimer();
		this.animate.bind(this)();
		return false;
		
	}.bind(this);
	
	divSliderMinus.onmouseover = function() { 
		this.minus.style.left = '-2000px';
		this.minusOver.style.left = '0px';
	}.bind(this);
	
	divSliderMinus.onmouseout = function() {
		this.minus.style.left = '0px';
		this.minusOver.style.left = '-2000px';
	}.bind(this);
	
	
	divSliderTicks.style.zIndex = 6;
	
	divSliderBG.appendChild(divSliderKnob);
	divSliderBG.appendChild(divSliderTicks);
	divSlider.appendChild(divSliderPlus);
	divSlider.appendChild(divSliderBG);
	divSlider.appendChild(divSliderMinus);	
	this.mdvMap.viewport.appendChild(divSlider);
	
	
	function createDiv(id) {
		var div = document.createElement('div');
		div.id = id;
		return div;
	}
		
};

MDVMapSlider.prototype.loadImages = function() {
	
	for(var i in this.imgs) {
		MDVMapSliderImages[i] = new Image();
		MDVMapSliderImages.over[i] = new Image();
				
		if (i === 'bg') {
			MDVMapSliderImages[i].failCount = 0;
			MDVMapSliderImages[i].onload = function() {
												this.setImages();
												this.drawTicks();
												this.createKnob();
												
												mdvLib.correctPNG(this.mdvMap, [this.plus, this.plusOver,
												this.minus, this.minusOver, this.bg, this.knob])
											
											}.bind(this);
											
			MDVMapSliderImages[i].onerror = function() {
												if (this.mdvMap) {
													MDVMapSliderImages.bg.failCount++;
													var failSrc = MDVMapSliderImages.bg.src;
													if (MDVMapSliderImages.bg.failCount <= 10) {
														MDVMapSliderImages.bg.src = failSrc;
													} else {	
														return;
													}
												}
											}.bind(this);								
		}
		
		MDVMapSliderImages[i].src = this.imagePath + this.imgs[i];
		MDVMapSliderImages.over[i].src = this.imagePath + this.imageRolloverPath + this.imgs[i];
		 
	}
}; 

MDVMapSlider.prototype.setImages = function() {
	
	var that = this;
	
	this.plus = mdvLib.createImg(
		{
			position: 'absolute',
			left: '0px'
		},
		{	
			src: MDVMapSliderImages.plus.src,
			id: 'MDVMapSliderPlus',
			title: this.text['zoomIn'],
			alt: this.text['zoomIn']
		});
		
	this.plusOver = mdvLib.createImg(
		{
			position: 'absolute',
			left: '-2000px'
		},
		{	
			src: MDVMapSliderImages.over.plus.src,
			id: 'MDVMapSliderPlusOver',
			title: this.text['zoomIn'],
			alt: this.text['zoomIn']
		});	
		
	var plusDiv = mdvLib.$('divSliderPlus');
	plusDiv.appendChild(this.plus);
	plusDiv.appendChild(this.plusOver);
		
	this.bg = mdvLib.createImg(
		{},
		{	
			id: 'MDVMapSliderBg',
			src: MDVMapSliderImages.bg.src,
			zIndex: 2,
			onclick: that.setKnob.bind(that),
			onmousemove: that.onKnobMove.bind(that),
			onmouseup: that.onKnobUp.bind(that)
		});
		
	this.bgPos = mdvLib.getElementPosition(mdvLib.$('divSliderBG'));
	
	this.garbage.push(['bg', 'onclick'],['bg', 'onmousemove'],['bg', 'onmouseup']);
	mdvLib.$('divSliderBG').appendChild(this.bg);
		
	
	this.minus = mdvLib.createImg(
		{
			position: 'absolute',
			left: '0'
		},
		{	
			src: MDVMapSliderImages.minus.src,
			id: 'MDVMapSliderMinus',
			title: this.text['zoomOut'],
			alt: this.text['zoomOut']
		});
		
	this.minusOver = mdvLib.createImg(
		{
			position: 'absolute',
			left: '-2000px'
		},
		{	
			src: MDVMapSliderImages.over.minus.src,
			id: 'MDVMapSliderMinusOver',
			title: this.text['zoomOut'],
			alt: this.text['zoomOut']
		});	
		
	var minusDiv = mdvLib.$('divSliderMinus');
	minusDiv.appendChild(this.minus);
	minusDiv.appendChild(this.minusOver);			
};


MDVMapSlider.prototype.drawTicks = function() {
	var tickMargin = Math.floor((MDVMapSliderImages.bg.height - this.tickOffset) / this.zoomLevels);
	var tickPos = MDVMapSliderImages.bg.height - this.tickOffset;
	var that = this;
	this.tickDiv = mdvLib.$('divSliderTicks');
	
	// write first tick
	this.tickDiv.appendChild(createTick(tickPos));
	this.tickPositions.push(tickPos);
	tickPos = tickPos - tickMargin;
	
	// ...and do the rest
	for(var i = 2; i <= this.zoomLevels; i++) {
		this.tickDiv.appendChild(createTick(tickPos));
		this.tickPositions.push(tickPos);
		tickPos = tickPos - tickMargin;
	}
	
	
	
	function createTick(pos) {
		
		var img = document.createElement('img');
		img.src = MDVMapSliderImages.tick.src;
		img.style.position = 'absolute';
	    img.style.top = pos + 'px';
   	    img.style.left = that.tickOffsetLeft + 'px';
   	    img.id = "tick" + pos;
   	    
		return img;
	}
	
};

MDVMapSlider.prototype.createKnob = function() {
	
	this.knobDiv = mdvLib.$('divSliderKnob');
	var that = this;
	
	mdvLib.style([this.knobDiv], {
			position: 'absolute',
			top: (this.tickPositions[this.getZoomLevel()] - (Math.floor(MDVMapSliderImages.knob.height/2))) + 'px',
			left: '1px',
			zIndex: 5
	});
	
	this.knob = mdvLib.createImg(
		{},
		{	
			src: MDVMapSliderImages.knob.src,
			id: 'MDVMapSliderKnob',
			onmousedown: function(){
				that.knobActive = true;
				that.clearTimer();
				return false;
			},
			onmousemove: that.onKnobMove.bind(that),
			onmouseup: that.onKnobUp.bind(that)
		} 
	);
	
	this.garbage.push(['knob', 'onmousedown'], ['knob', 'onmousemove'], ['knob', 'onmouseup']);
	
	this.indicator = mdvLib.createImg(
		{
			position: 'absolute',
			top: that.tickPositions[this.getZoomLevel()] + (Math.floor(MDVMapSliderImages.knob.height/2)) - 3 + 'px',
			left: '8px',
			zIndex: 3
		},
		{	
			id: 'MDVMapSliderIndicator',
			src: MDVMapSliderImages.indicator.src,
			height: that.tickPositions[0]-that.tickPositions[this.getZoomLevel()] + 7,
			width: MDVMapSliderImages.indicator.width,
			onclick: that.setKnob.bind(that),
			resize: function(posTop, plus) {
				this.height = (plus)? this.height+1 : this.height-1;
				this.style.top = posTop + (Math.floor(MDVMapSliderImages.knob.height/2)) + 'px';
				return true;
			}
		});
		
	this.garbage.push(['indicator', 'onclick']);
	this.knobDiv.appendChild(this.knob);
	mdvLib.$('divSliderBG').appendChild(this.indicator);
	
	this.mdvMap.events.registerEvent(MDVEvent_ZOOM_CHANGED, this, this.onZoomChanged);
	this.init = true;
	this.clearTimer();
};

MDVMapSlider.prototype.setKnob = function(e) {

	var e = e || window.event;
	this.clearTimer();
	var posMouse = mdvLib.getMousePosition(e);
	var posMouseEl = MDVMapSliderImages.bg.height - (posMouse.top - this.bgPos.top);
	var hlp = this.tickPositions.slice().reverse();
	
	for(var i = 0; i < hlp.length; i++) {
		if (posMouseEl <= hlp[i+1]) {
			var to = (posMouseEl <= ((hlp[i] + hlp[i+1]) / 2)) ? i : i+1;
			this.setZoomLevel(parseInt(to, 10));
			break;
		} 	
	}
	
	// handle click above topmost tick
	if (posMouseEl >= hlp[this.zoomLevels-1]) {
		this.setZoomLevel(this.zoomLevels-1);
	}
	
	this.animate();
	return true;
}; 

MDVMapSlider.prototype.animate = function() {
	
	this.timer = window.setInterval(move.bind(this), this.timerDelay);
	
	var currentPos = parseInt(this.knobDiv.style.top, 10);
	var targetPos = this.tickPositions[this.currentLevel] - Math.floor(MDVMapSliderImages.knob.height/2);
	
	function move() {
		
		if (targetPos > currentPos) {
			currentPos++;
			this.knobDiv.style.top = currentPos + 'px';
			this.indicator.resize(currentPos, false);
			return;
		}
		
		if (targetPos < currentPos) {
			currentPos--;
			this.knobDiv.style.top = currentPos + 'px';
			this.indicator.resize(currentPos, true);
			return;
		}
	
		this.clearTimer();	
	}
};

	
MDVMapSlider.prototype.clearTimer = function() {
	window.clearInterval(this.timer);
	window.clearTimeout(this.timer);
	this.timer = null;
};

MDVMapSlider.prototype.setZoomLevel = function(value) {
		
		if (value === this.currentLevel) {
			return true;
		}
		
		var magnify = (this.mdvMap.config.get('useMagnifyGlass') &&
						this.mdvMap.config.get('useMagnifyGlass') == 'true');
		
		if (magnify && (this.currentLevel < value)) {
			this.currentLevel = value;
			this.mdvMap._checkWrap();
			this.mdvMap.magnify(value);
			this.mdvMap.switchMapper();
		} else {
			this.currentLevel = value;
			this.mdvMap.setZoomLevel(value);
			this.mdvMap.update();
		}
		return true;
};

MDVMapSlider.prototype.onZoomChanged = function() {
	
	if(this.currentLevel == this.getZoomLevel()) {
		return;
	}
	this.clearTimer();
	this.currentLevel = this.getZoomLevel();
	this.animate();
};

MDVMapSlider.prototype.getZoomLevel = function() {
	return (typeof this.mdvMap.config.getZoomLevelIndex() === 'number') ?
		 this.mdvMap.config.getZoomLevelIndex() : this.mdvMap.config.params.defaultScale;
};

MDVMapSlider.prototype.onKnobMove = function(e) {
	
	
	if(this.knobActive !== true) {
		return true;
	}	
	
	var e = e || window.event;
	
	var posMouse = mdvLib.getMousePosition(e);
	var knobTop = (posMouse.top - (this.bgPos.top + Math.floor(this.knob.height/2)));
	var knobTopCurrent = parseInt(this.knobDiv.style.top, 10);
	
	// prevent knob from being dragged past available zoom levels 
	if ((knobTop < this.tickPositions[this.zoomLevels-1]) || (knobTop > this.tickPositions[0])) {
		return true;
	}
	
	if (knobTopCurrent > knobTop) {
		// indicator.resize method is inaccurate here
		// move steps can be > 1 
		this.indicator.style.top = knobTop + (Math.floor(MDVMapSliderImages.knob.height/2)) + 'px';
		this.indicator.height = this.indicator.height + (knobTopCurrent - knobTop);
	} else {
		this.indicator.style.top = knobTop + Math.floor((MDVMapSliderImages.knob.height/2)) + 'px';
		this.indicator.height = this.indicator.height - (knobTop - knobTopCurrent);
	}

	this.knobDiv.style.top = knobTop + 'px';
	return false;
};

MDVMapSlider.prototype.onKnobUp = function(e) {
	
	if(this.knobActive === true) {
		this.knobActive = false;
		this.setKnob(e);
	}
	return false;
};

MDVMapSlider.prototype._execute = function() {
	
	if (this.init === true) {
		return;
	}
	this.currentLevel = this.getZoomLevel();
	this.zoomLevels = this.mdvMap.config.zoomLevels.length;
	
	this.createContainer();
	this.loadImages();
	//this.init = true;
};

var MDVMapSliderImages = {
	over: {}
};


