
function VideoEngineCallback() {}

VideoEngineCallback.prototype.onBeforeVideo = function (eventFull) {}

VideoEngineCallback.prototype.onStartedVideo = function (eventFull) {}

VideoEngineCallback.prototype.onUpdateVideo	= function (eventFull) {}

VideoEngineCallback.prototype.onError = function (eventFull) {}

VideoEngineCallback.prototype.onStateChange	= function (eventFull, newState) {}

VideoEngineCallback.prototype.getWidth = function () {return 425;}

VideoEngineCallback.prototype.getHeight = function () {return 344;}

function VideoEngine() {}

VideoEngine.prototype.isStopped = false;

VideoEngine.prototype.isOnSchedule = false;

VideoEngine.prototype.start = function (stationID, callback) {
	consoleLog.info("> VideoEngine.start");
	this.init(stationID, callback);
	this.requestVideoFromServer();
	consoleLog.info("< VideoEngine.start");
}

VideoEngine.prototype.init = function (stationID, callback) {
	consoleLog.info("> VideoEngine.init");
	this.isStopped = false;
	this.isOnSchedule = true;
	this.stationID = stationID;
	this.callback = callback;
	youTubeImpl.init(stationID, callback);
	consoleLog.info("< VideoEngine.init");
}

VideoEngine.prototype.requestVideoFromServer = function () {
	consoleLog.info("> VideoEngine.requestVideoFromServer");
	consoleLog.info("  isOnSchedule = " + this.isOnSchedule);
	if (this.eventFull == undefined || this.isOnSchedule) {
		consoleLog.info("  getEvent(" + this.stationID + ")");
		Router.getEvent(this.stationID, onEventFromServer);
	} else {
		consoleLog.info("  getNextEvent() " + this.stationID + ":stationID, " + this.eventFull.event.eventID + ":eventID");
		Router.getNextEvent(this.stationID, this.eventFull.event.eventID, onEventFromServer);
	}
	consoleLog.info("< VideoEngine.requestVideoFromServer");
}

VideoEngine.prototype.stop = function () {
	consoleLog.info("> VideoEngine.stop");
	this.isStopped = true;
	switch (this.eventFull.media.providerID) {
		case 1:
			youTubeImpl.stop();
			break;
		case 2:
			break;
	}
	consoleLog.info("< VideoEngine.stop");
}

VideoEngine.prototype.getMediaByID = function (mediaID) {
	consoleLog.info("> VideoEngine.getMediaByID " + mediaID);
	this.isStopped = false;
	Router.getMediaByID(mediaID, onEventFromServer);
	consoleLog.info("< VideoEngine.getMediaByID " + mediaID);
}

VideoEngine.prototype.getEventByID = function (eventID) {
	consoleLog.info("> VideoEngine.getEventByID " + eventID);
	this.isStopped = false;
	this.isOnSchedule = false;
	Router.getEventByID(eventID, onEventFromServer);
	consoleLog.info("< VideoEngine.getEventByID " + eventID);
}

VideoEngine.prototype.getEventByIDAndTime = function (eventID, posSeconds) {
	consoleLog.info("> VideoEngine.getEventByIDAndTime(" + eventID + ", " + posSeconds + ")");
	this.isStopped = false;
	this.isOnSchedule = false;
	Router.getEventWithPos(eventID, parseInt(posSeconds), onEventFromServer);
	consoleLog.info("< VideoEngine.getEventByIDAndTime");
}

VideoEngine.prototype.getPrevEvent = function () {
	consoleLog.info("> VideoEngine.getPrevEvent");
	this.isStopped = false;
	this.isOnSchedule = false;
	if (this.eventFull.event.eventID > 0) {
		Router.getPrevEvent(this.stationID, this.eventFull.event.eventID, onEventFromServer);
	}
	consoleLog.info("< VideoEngine.getPrevEvent");
}

VideoEngine.prototype.getCurrEvent = function () {
	consoleLog.info("> VideoEngine.getCurrEvent");
	this.isStopped = false;
	this.isOnSchedule = true;
	if (this.eventFull.event.eventID > 0) {
		Router.getEvent(this.stationID, onEventFromServer);
	}
	consoleLog.info("< VideoEngine.getCurrEvent");
}

VideoEngine.prototype.reloadCurrEvent = function () {
	consoleLog.info("> VideoEngine.reloadCurrEvent");
	this.isStopped = false;
	this.isOnSchedule = true;
	if (this.eventFull.event.eventID > 0) {
		this.eventFull = null;
		Router.getEvent(this.stationID, onEventFromServer);
	}
	consoleLog.info("< VideoEngine.reloadCurrEvent");
}

VideoEngine.prototype.getCurrentTimeMS = function () {
	consoleLog.info("> VideoEngine.getCurrentTimeMS()");
	if ($(etherTVPlayerName)) {
		return $(etherTVPlayerName).getCurrentTime();
	}
	return 0;
}

VideoEngine.prototype.reloadSelectedEvent = function () {
	consoleLog.info("> VideoEngine.reloadSelectedEvent");
	this.isStopped = false;
	this.isOnSchedule = false;
	if (this.eventFull.event.eventID > 0) {
		var eventID = this.eventFull.event.eventID;
		var posSeconds = $(etherTVPlayerName).getCurrentTime();
		this.eventFull = null;
		Router.getEventWithPos(eventID, parseInt(posSeconds), onEventFromServer);
	}
	consoleLog.info("< VideoEngine.reloadSelectedEvent");
}

VideoEngine.prototype.getEventByIDAndTime = function (eventID, posSeconds) {
	consoleLog.info("> VideoEngine.getEventByIDAndTime(" + eventID + ", " + posSeconds + ")");
	this.isStopped = false;
	this.isOnSchedule = false;
	Router.getEventWithPos(eventID, parseInt(posSeconds), onEventFromServer);
	consoleLog.info("< VideoEngine.getEventByIDAndTime");
}

VideoEngine.prototype.getNextEvent = function () {
	consoleLog.info("> VideoEngine.getNextEvent");
	this.isStopped = false;
	this.isOnSchedule = false;
	if (this.eventFull.event.eventID > 0) {
		Router.getNextEvent(this.stationID, this.eventFull.event.eventID, onEventFromServer);
	}
	consoleLog.info("< VideoEngine.getNextEvent");
}

VideoEngine.prototype.eventReceivedFromServer = function (eventFull) {
	consoleLog.info("> VideoEngine.eventReceivedFromServer() " + eventFull.media.mediaID + ":mediaID");
	var eventIsDifferent =
		this.eventFull == undefined ||
		this.eventFull.media.mediaID != eventFull.media.mediaID;

	consoleLog.info("  eventIsDifferent = " + eventIsDifferent);
	
	this.eventFull = eventFull;

	youTubeImpl.eventFull = eventFull;
	if (eventIsDifferent) {
		Router.viewEvent(
			eventFull.event.stationID,
			eventFull.media.mediaID,
			eventFull.event.eventID);
		switch (this.eventFull.media.providerID) {
			case 1:
				youTubeImpl.eventReceivedFromServer(eventFull);
				break;
			case 2:
				googleVideoImpl.eventReceivedFromServer(eventFull);
				break;
		}
	} else {
		this.callback.onUpdateVideo(eventFull);
	}
	consoleLog.info("< VideoEngine.eventReceivedFromServer()");
}

var videoEngine = new VideoEngine();

function onEventFromServer(eventFull) {
	videoEngine.eventReceivedFromServer(eventFull);
}

var vidparams = "&amp;border=0&amp;enablejsapi=1&amp;playerapiid=ytplayer";
var etherTVPlayerName = "ethertvplayer";
var etherTVDivName = "ethertvdiv";
var etherTVControlName = "ethertvcontrol";

var YouTubeStates = {
	"UNSTARTED":-1,
	"ENDED":0,
	"PLAYING":1,
	"PAUSED":2,
	"BUFFERING":3,
	"VIDEO_CUED":5};

function YouTubeImpl() {}

YouTubeImpl.prototype.errorCode = 0;

YouTubeImpl.prototype.init = function (stationID, callback) {
	this.stationID = stationID;
	this.callback = callback;
	this.errorCode = 0;
}

YouTubeImpl.prototype.stop = function () {
	$(etherTVPlayerName).stopVideo();
}

YouTubeImpl.prototype.eventReceivedFromServer = function (eventFull) {
	consoleLog.info("> YouTubeImpl.eventReceivedFromServer() " + eventFull.media.mediaID + ":mediaID");
	if (window.swfobject === undefined) {
		alert("Flash library not available!");
		return;
	}

	// Create the embeded URL
	this.errorCode = 0;
	this.eventFull = eventFull;
	var eventURL = eventFull.media.mediaURL;
	var equalsPos = eventURL.lastIndexOf("=");
	eventURL = "http://www.youtube.com/v/" + eventURL.substring(equalsPos + 1);

	// Prepare the video, this will trigger onYouTubePlayerReady()
	var params = { allowScriptAccess: "always" };
	var atts = { id: etherTVPlayerName };
	$(etherTVDivName).innerHTML = "<div id=\"" + etherTVControlName + "\"></div>";
	consoleLog.info("  swfobject=" + swfobject);
	swfobject.embedSWF(
		eventURL + vidparams, 
		etherTVControlName, this.callback.getWidth(), this.callback.getHeight(),
		"8", null, null, params, atts);
	consoleLog.info("< YouTubeImpl.eventReceivedFromServer()");
}

YouTubeImpl.prototype.onPlayerReady = function (playerId) {
	consoleLog.info("> YouTubeImpl.onPlayerReady()");
	$(etherTVPlayerName).addEventListener("onStateChange", "onPlayerStateChange");
	$(etherTVPlayerName).addEventListener("onError", "onPlayerError");
	this.callback.onBeforeVideo(this.eventFull);
	consoleLog.info("  calling seekTo() " + this.eventFull.startOffset.seconds + ":startOffset");
	$(etherTVPlayerName).seekTo(this.eventFull.startOffset.seconds, true);
	consoleLog.info("< YouTubeImpl.onPlayerReady()");
}

YouTubeImpl.prototype.onPlayerStateChange = function (newState) {
	var stateName = $H(YouTubeStates).keys()[$H(YouTubeStates).values().indexOf(newState)];
	consoleLog.info("> YouTubeImpl.onPlayerStateChange() " + stateName + ":stateName");

	this.callback.onStateChange(this.eventFull, newState);
	if (videoEngine.isStopped) return;

	var offsetDiff = this.eventFull.startOffset.seconds - $(etherTVPlayerName).getCurrentTime(); 
	consoleLog.info(
		"  startOffset, currentTime, offsetDiff: " +
		this.eventFull.startOffset.seconds + ", " +
		$(etherTVPlayerName).getCurrentTime() + ", " +
		offsetDiff);
	if (offsetDiff > 2 && newState == YouTubeStates.PLAYING && this.errorCode == 0) {
		consoleLog.info("  calling seekTo() " + this.eventFull.startOffset.seconds + ":startOffset");
		$(etherTVPlayerName).seekTo(this.eventFull.startOffset.seconds, true);
	}

	if (newState == YouTubeStates.ENDED) {
		videoEngine.requestVideoFromServer();
	}

	var duration = parseInt($(etherTVPlayerName).getDuration());

	consoleLog.info("  duration = " + duration);
	consoleLog.info("  this.eventFull.media.duration = " + this.eventFull.media.duration);

	if (durationHasChanged(duration, this.eventFull.media.duration)) {
		Router.setMediaDuration(
			this.eventFull.event.eventID,
			this.eventFull.media.mediaID,
			duration * 1000,
			onEventFromServer);
	}
	
	if (newState == YouTubeStates.PLAYING) {
		Router.clearMediaErrorCount(this.eventFull.media.mediaID);
		this.callback.onStartedVideo(this.eventFull);		
	}

	consoleLog.info("< YouTubeImpl.onPlayerStateChange()");
}

function durationHasChanged(duration, mediaDuration) {
	return !isNaN(duration) &&
		duration > 5 &&
		!((duration - 2) * 1000 < mediaDuration &&
		(duration + 2) * 1000 > mediaDuration);
}

YouTubeImpl.prototype.onPlayerError = function (errorCode) {
	consoleLog.info("> YouTubeImpl.onPlayerError() " + errorCode + ":errorCode");
	this.errorCode = errorCode;
	errorMsg = "unknown";
	switch (errorCode) {
		case 100:
			errorMsg = "The requested video was not found.";
			break;
		case 101:
		case 150:
			errorMsg = "The requested video cannot be embedded.";
			break;
		default:
			errorMsg += " (" + errorCode + ")"; 
			break;
	}
	Router.incrementMediaErrorCount(this.eventFull.media.mediaID);
	alert("An error occurred: " + errorMsg);
	this.callback.onError(this.eventFull);		
	consoleLog.info("< YouTubeImpl.onPlayerError()");
}

var youTubeImpl = new YouTubeImpl();

function onYouTubePlayerReady(playerId) {
	youTubeImpl.onPlayerReady(playerId);
}

function onPlayerStateChange(newState) {
	youTubeImpl.onPlayerStateChange(newState);
}

function onPlayerError(errorCode) {
	youTubeImpl.onPlayerError(errorCode);
}

function GoogleVideoImpl() {}

GoogleVideoImpl.prototype = new YouTubeImpl();

GoogleVideoImpl.prototype.constructor = YouTubeImpl;

GoogleVideoImpl.prototype.eventReceivedFromServer = function (eventFull) {
	if (window.swfobject === undefined) {
		alert("Flash library not available!");
		return;
	}

	// Create the embeded URL
	this.eventFull = eventFull;
	var eventURL = eventFull.media.mediaURL;
	var equalsPos = eventURL.lastIndexOf("=");

	// Prepare the video, this will trigger onYouTubePlayerReady()
	var params = { allowScriptAccess: "always" };
	var atts = { id: etherTVPlayerName };
	$(etherTVDivName).innerHTML = "<div id=\"" + etherTVControlName + "\"></div>";
	swfobject.embedSWF(
		eventURL + vidparams, 
		etherTVControlName, "425", "344", "8", null, null, params, atts);
}

var googleVideoImpl = new GoogleVideoImpl();

