///////////////////////////////////////////////////////////////////////////////
//
//  player.js   			version 1.0
//  2008 
//	Authored by: Lenny Burdette
//  Modified by: Jeff Miller
//      
//
//  FUNCTIONS:
//			HSN.Player
//			HSN.ControlButton
// 			HSN.ScrubBar
//			HSN.Volume
//			
//	DEPENDENCIES:
//			Utils2.js
//
///////////////////////////////////////////////////////////////////////////////

if ( !window.HSN) { window.HSN = {}; }

HSN.Player = function(params) {
	this.type = params.type; // either mini or super mini
	this.source = params.source;
	this.live = params.live;
	this.params = params;
	this.host = HSN.root;

	this.downloader = new Silverlight.Downloader({
		resource : "cmn/xaml/" + this.type + "video.xaml",
		plugin: HSN.plugin,
		onComplete : this.xamlLoaded.bind(this)
	});
}

HSN.Player.prototype = {
	init : function() {
		if (!this.self) { return; }

		// get elements
		this.media = this.self.findName('media');
		this.replayBackground = this.self.findName('replayBackground');
		this.muteButton = this.self.findName('muteButton');
		this.muteButtonSelected = this.self.findName('muteButton_selected');
		this.volume = this.self.findName('volume');
		this.timer = document.getElementById('timer');

		// controls
		this.muteButton = new HSN.MuteButton('muteButton', this.self.findName('muteButton'), this.self.findName('volume'), this.setMute.bind(this));
		this.volumeBars = new HSN.Volume(this.self.findName('volume'), 14, this.setVolume.bind(this), this.unMute.bind(this));
		this.playButton = new HSN.ControlButton('playButton', this.self.findName('playButton'), this.media, this.live, this.play.bind(this));
		this.scrubBar = new HSN.ScrubBar(this.self.findName('scrubBar'), this.setPosition.bind(this));
		
		// set up events
		this.media.addEventListener('MediaOpened', this.onMediaOpened.bind(this));
		this.media.addEventListener('MediaEnded', this.onMediaEnded.bind(this));
		this.media.addEventListener('MediaFailed', this.onMediaFailed.bind(this));
		this.media.addEventListener('Loaded', this.onMediaLoaded.bind(this));
		this.media.addEventListener('BufferingProgressChanged', this.onBufferingProgressChanged.bind(this));
		this.media.addEventListener('CurrentStateChanged', this.onCurrentStateChanged.bind(this));
		this.media.addEventListener('DownloadProgressChanged', this.onDownloadProgressChanged.bind(this));

		if (this.params.hidden) {
			this.hide();
		} else {
			this.hidden = false;
		}

		if (this.params.onLoad) {
			this.params.onLoad();
		}
		this.begin();
	},

	xamlLoaded : function(downloader, args) {
		var xamlText = downloader.responseText; 
		this.fragment = HSN.plugin.content.createFromXaml(xamlText, true);
		this.host.children.add(this.fragment);
		this.self = this.fragment.findName(this.type);

		this.position(5, 290);
		this.init();
	},

	position : function(top, left) {
		var oldTop = this.self['Canvas.Top'];
		var oldLeft = this.self['Canvas.Left'];
		this.self['Canvas.Top'] = top || oldTop;
		this.self['Canvas.Left'] = left || oldLeft;
	},

	begin : function() {
		if (this.source) {
			this.media.source = this.source;
		}
		this.startTimer();
	},

	setSource : function(source, live) {
		this.source = source;
		this.live = live;
		this.setTimer();
		this.playButton.deselect(this.live);
		this.begin();
	},

	/****************************
	*		Media Events		*
	****************************/

	onMediaOpened : function() {
		this.mediaOpened = true;
		this.playButton.enable();
		this.scrubBar.enable();
		this.replayBackground.visibility = 'collapsed';
		this.volumeBars.enable();
	},

	onMediaEnded : function() {
		this.setTimer();
		this.playButton.deselect();
		this.scrubBar.goToBeginning(0);
		this.replayBackground.visibility = 'visible';
		this.media.opacity = 0;
		this.media.cursor = 'Hand';
		this.media.addEventListener('MouseLeftButtonDown', this.play.bind(this));
		this.media.stop();
	},

	onMediaFailed : function() {
		this.setTimer();
		this.playButton.deselect();
		this.rewind();
	},

	onMediaLoaded : function() {
		this.mediaLoaded = true;
	},

	onBufferingProgressChanged : function() {
		// this.scrubBar.updateBuffer(this.media.bufferingProgress);
	},

	onCurrentStateChanged : function() {
		// console.log('current state: ' + this.media.currentState);
	},

	onDownloadProgressChanged : function() {
		this.scrubBar.updateBuffer(this.media.downloadProgress);
	},

	startTimer : function() {
		if (this.updateTimerId) {
			clearInterval(this.updateTimerId);
			this.updateTimerId = null;
			delete this.updateTimerId;
		}
		this.timer.innerHTML = '';
		this.updateTimerId = setInterval(this.updateTimer.bind(this), 100);
	},

	updateTimer : function() {
		var time = Math.ceil(this.media.position.seconds),
			minutes = Math.floor(time / 60),
			seconds = time % 60;
		this.timer.innerHTML = '';
		if (this.live != true) {
			this.timer.innerHTML = this.calculateTime(this.media.naturalDuration.Seconds - time);
		}
		this.scrubBar.updatePosition(this.media.position, this.media.naturalDuration);
		if (this.media.mediaEnded) {
			this.onMediaEnded();
		}
	},

	setTimer : function() {
		var durationString = this.calculateTime(this.media.naturalDuration.seconds);
		this.timer.innerHTML = durationString;
	},

	calculateTime : function (seconds) {
		var datetime = new Date(0, 0, 0, 0, 0, seconds);
		var minutes = datetime.getMinutes();
		var seconds = datetime.getSeconds();
		minutes = (minutes < 10) ? '0' + minutes : minutes;
		seconds = (seconds < 10) ? '0' + seconds : seconds;

		return minutes + ':' + seconds
	},


	/****************************
	*		Mouse Events		*
	****************************/

	play : function() {
		this.media.opacity = 1;
		if (this.media.currentState == 'Playing') {
			this.media.pause();
			this.playButton.select();
			this.setTimer();
		} else {
			this.media.play();
			this.playButton.deselect(this.live);
			this.startTimer();
		}
	},

	pause : function() {
		this.media.pause();
		this.playButton.select();
	},

	rewind : function() {
		if (this.media.canSeek) {
			var temp = this.media.position;
			temp.seconds = 0;
			this.media.position = temp;
			this.scrubBar.goToBeginning(0);
			this.startTimer();
		}
	},

	setVolume : function(level) {
		if (level == 'undefined') {
			level = .5;
		}
		this.media.volume = level;
	},

	setMute : function(status) {
		if (status == 'undefined') {
			status = false;
		}
		this.media.isMuted = status;
	},

	unMute : function() {
		this.muteButton.visibility = 'visible';
		this.muteButtonSelected.visibility = 'collapsed';
		this.volume.opacity = 1;
		this.media.isMuted = false;
	},

	setPosition : function(ratio) {
		var temp = this.media.position,
			newTime = this.media.naturalDuration.seconds * ratio;
		temp.seconds = newTime;
		this.media.position = temp;
	},

	show : function() {
		this.play();
		this.self.visibility = 'visible';
		this.hidden = false;
	},

	hide : function() {
		this.pause();
		this.self.visibility = 'collapsed';
		this.hidden = true;
	}
}

HSN.MuteButton = function(id, xaml, volume, callback) {
	this.id = id;
	this.xaml = xaml;
	this.volume = volume;
	this.callback = callback;
	this.initEvents();
}

HSN.MuteButton.prototype = {
	initEvents : function() {
		// hit area and mouse events
		this.hit = this.xaml.findName(this.id + '_hit');
		this.hit.cursor = 'Hand';
		this.hit.addEventListener('MouseLeftButtonDown', this.onClick.bind(this));

		// states
 		this.selectedState = this.xaml.findName(this.id + '_selected');
	},

	onClick : function() {
		if (this.selectedState) {
			if (this.selected) {
				this.selected = false;
				this.selectedState.visibility = 'collapsed';
				this.volume.opacity = 1;
				this.callback(false);
			} else {
				this.selected = true;
				this.selectedState.visibility = 'visible';
				this.volume.opacity = 0;
				this.callback(true);
			}
		}
	}
}

HSN.ControlButton = function(id, xaml, media, live, callback) {
	this.id = id;
	if (! xaml) {
		return false;
	}
	this.xaml = xaml;
	this.media = media;
	this.live = live;
	this.callback = callback;
	this.initEvents();
	this.disable();
}
HSN.ControlButton.prototype = {
	initEvents : function() {
		// hit area and mouse events
		this.hit = this.xaml.findName(this.id + '_hit');
		this.hit.cursor = 'Hand';
		this.hit.addEventListener('MouseEnter', this.onOver.bind(this));
		this.hit.addEventListener('MouseLeave', this.onOut.bind(this));
		this.hit.addEventListener('MouseLeftButtonDown', this.onClick.bind(this));

		// states
		this.stopOver = this.xaml.findName(this.id + '_over');
 		this.play = this.xaml.findName(this.id + '_play');
 		this.playOver = this.xaml.findName(this.id + '_play_over');
 		this.pause = this.xaml.findName(this.id + '_pause');
 		this.pauseOver = this.xaml.findName(this.id + '_pause_over');
	},

	onOver : function() {
		if (this.live) {
			if (this.selected) {
				this.playOver.visibility = 'visible';
			} else {
				this.stopOver.visibility = 'visible';
			}
		} else if (this.selected) {
			this.playOver.visibility = 'visible';
		} else {
			if (this.media.currentstate == "Playing") {
				this.pauseOver.visibility = 'visible';
			} else {
				this.playOver.visibility = 'visible';
			}
		}
	},

	onOut : function() {
		if (this.live) {
			this.stopOver.visibility = 'collapsed';
		} else if (this.selected) {
			this.pause.visibility = 'collapsed';
		} else {
			this.pauseOver.visibility = 'collapsed';
		}
		this.playOver.visibility = 'collapsed';
	},

	onClick : function() {
		this.callback();
		if (this.play) {
			if (this.live) {
				if (this.selected) {
					this.selected = true;
					this.play.visibility = 'visible';
				} else {
					this.selected = false;
					this.play.visibility = 'collapsed';
				}
			} else if (this.selected) {
				this.selected = true;
				this.play.visibility = 'visible';
				this.pauseOver.visibility = 'collapsed';
			} else {
				this.selected = false;
				this.play.visibility = 'collapsed';
			}
		}
	},

	enable : function() {
		this.disabled = false;
		this.hit.visibility = 'visible';
	},

	disable : function() {
		this.disabled = true;
		this.hit.visibility = 'collapsed';
	},

	select : function() {
		this.selected = true;
		if (this.play) {
			this.play.visibility = 'visible';
		}
	},

	deselect : function(live) {
		this.live = live;
		this.selected = false;
		if (this.play) {
			if (this.live) {
				this.play.visibility = 'collapsed';
				this.pause.visibility = 'collapsed';
			} else {
				if (this.media.currentstate == "Paused") {
					this.play.visibility = 'visible';
					this.pause.visibility = 'collapsed';
				} else {
					this.pause.visibility = 'visible';
				}
			}
		} else {
			this.play.visibility = 'collapsed';
		}
	}
}

HSN.ScrubBar = function(xaml, callback) {
	this.xaml = xaml;
	this.callback = callback;
	this.getElements();
	this.initEvents();
	this.disable();
}
HSN.ScrubBar.prototype = {
	getElements : function() {
		this.track = this.xaml.findName('track');
		this.downloadBar = this.xaml.findName('downloadBar');
		this.scrubber = this.xaml.findName('scrubber');
		this.hit = this.xaml.findName('scrubberHit');
	},

	initEvents : function() {
		this.hit.cursor = 'Hand';
		this.hit.addEventListener('MouseLeftButtonDown', this.onClick.bind(this));
		this.hit.addEventListener('MouseLeftButtonUp', this.onRelease.bind(this));
		this.hit.addEventListener('MouseMove', this.onDrag.bind(this));
	},

	updateBuffer : function(amount) {
		this.downloadBar.width = this.track.width * amount;
	},

	updatePosition : function(current, total) {
		if (this.captured) {
			return;
		}
		try {
			this.scrubber['Canvas.Left'] = (this.track.width - this.scrubber.width) * (current.seconds / total.seconds);
		} catch(e) {}
	},

	goToBeginning : function(position) {
		this.scrubber['Canvas.Left'] = 0;
	},

	/************************
	*	Dragging Callbacks	*
	************************/
	onClick : function(sender, e) {
		this.captured = true;
		sender.captureMouse();
		this.beginDragX = e.getPosition(null).x;
		this.hit.width = 12;
		this.hit['Canvas.Left'] = -1 * (12 - this.scrubber.width) / 2;
	},

	onRelease : function(sender) {
		this.captured = false;
		sender.releaseMouseCapture();
		this.hit.width = 12;
		this.hit['Canvas.Left'] = 0;
		this.respond();
	},

	onDrag : function(a, e) {
		if (this.captured) {
			var currentX = e.getPosition(null).x,
				deltaX = currentX - this.beginDragX,
				newX = this.scrubber['Canvas.Left'] + deltaX;
			newX = newX < 0 ? 0 : newX;
			newX = newX > this.track.width - this.scrubber.width ? this.track.width - this.scrubber.width : newX;
			this.scrubber['Canvas.Left'] = newX;
			this.beginDragX = currentX;
		}
	},

	enable : function() {
		this.disabled = false;
		this.hit.visibility = 'visible';
	},

	disable : function() {
		this.disabled = true;
		this.hit.visibility = 'collapsed';
	},

	respond : function() {
		var position = this.scrubber['Canvas.Left'] / (this.track.width - this.scrubber.width);
		this.callback(position);
	}
}

HSN.Volume = function(xaml, steps, callback, callback2) {
	this.xaml = xaml;
	this.steps = steps;
	this.callback = callback;
	this.callback2 = callback2;
	this.getElements();
	this.initEvents();
	this.level = 7;
	this.update();
	this.disable();
}
HSN.Volume.prototype = {
	getElements : function() {
		this.images = [];
		for (var i = 0; i <= this.steps; i++) {
			this.images.push(this.xaml.findName('volume_' + i));
			if (this.xaml.findName('volume_' + i).visibility != 'collapsed') {
				this.level = i;
			}
		}
		this.hit = this.xaml.findName('volume_hit');
	},

	initEvents : function() {
		this.hit.cursor = 'Hand';
		this.hit.addEventListener('MouseLeftButtonDown', this.onClick.bind(this));
		this.hit.addEventListener('MouseLeftButtonUp', this.onRelease.bind(this));
		this.hit.addEventListener('MouseMove', this.onMove.bind(this));
	},

	onClick : function(sender, event) {
		this.callback2();
		this.capture = true;
		this.hit.captureMouse();
		this.translate(event.getPosition(this.hit).x);
		this.update();
	},

	onRelease : function() {
		this.capture = false;
		this.hit.releaseMouseCapture();
	},

	onMove : function(sender, event) {
		if (this.capture) {
			this.translate(event.getPosition(this.hit).x);
			this.update();
		}
	},

	translate : function(pixels) {
		this.level = Math.round(pixels / this.hit.width * this.steps);
		this.level = this.level < 0 ? 0 : this.level;
		this.level = this.level > this.steps ? this.steps : this.level;
	},

	update : function() {
		for (var i = 0, image = null; image = this.images[i]; i++) {
			this.images[i].visibility = i == this.level ? 'visible' : 'collapsed';
		}
		this.callback(this.level / this.steps);
	},

	enable : function() {
		this.disabled = false;
		this.hit.visibility = 'visible';
	},

	disable : function() {
		this.disabled = true;
		this.hit.visibility = 'collapsed';
	}
}
