// utility method that duck-punches Object 
// to handle object construction & inheritance
if(typeof Object.beget !== 'function') {
	Object.beget = function(o) {
		var F = function() { };
		F.prototype = o;
		return new F();
	};
}
// now to make a new object based on the prototype 'foo', we go
// var bar = Object.beget(foo);



// flp_comm prototype 
// this object makes calls to the server and invokes the callback 
// provided by the object that intiated the call.
var flp_comm = {
	label : 'flp_comm',
	url_base : 'http://player2.entropymedia.com',
	cache_url_base : 'http://www.pbs.org',
	session_key : "0",
	track_session : function(json_data) {
		if(json_data.ses != this.session_key) { this.session_key = json_data.ses; }
	},
	getdir_fromcache : function(v) {
	$.jsonp({
		callback : 'get_json',
		callbackParameter : 'callback',
		context : v,
		cache : false,
		success : v.load_data,
		error : v.get_data_from_svc,  //need to hack jquery to modify jsonp callback
		url  : this.cache_url_base + '/wgbh/pages/frontline/.json/getdir/getdir' + v.pkg_id + '.json'
	})},
	getdir_fromsvc : function(v) {
		$.jsonp({
			callback : 'get_json',
			callbackParameter : 'callback',
			success : v.load_data,
			context : v,
			url  : this.url_base + '/json/core',
			data : {"method" : "getdir", "brn" : v.brand_id, "pkg" : v.pkg_id}	
	})},
	getrel_fromcache : function(v) {
		$.jsonp({
			callback : 'get_json',
			callbackParameter : 'callback',
			success : v.load_reldata,
			error : v.get_relc_from_svc,
			context : v,
			cache : false,
			url  : this.cache_url_base + '/wgbh/pages/frontline/.json/getrel/getrels' + v.seg_id + '.json' 
	})},
	getrel_fromsvc : function(v) {
		$.jsonp({
			callback : 'get_json',
			callbackParameter : 'callback',
			success : v.load_reldata,
			context : v, 
			url  : this.url_base + '/json/core',
			data : {"method" : "getrel", "seg" : v.seg_id, "pkg" : v.pkg_id}	
	})},
	sendlog : function(v,currenttime,sourcer) {
		$.jsonp({
			callback : 'get_json',
			callbackParameter : 'callback',
			success : this.track_session,
			context : this,
			url  : this.url_base + '/json/core',
			data : {"method" : "logtim", "seg" : v.seg_id, "pkg" : v.pkg_id, "ses" : this.session_key, "tim" : currenttime, "src" : sourcer }	
	})}

	
};

// video protoype
var flp_video = {
	label : 'flp_video',
	loaded : false,
	relloaded : false,
	isblocked : false,
	ispassword : false,
	mobilefriendly: false,
	fullshowmode: false,
	tp_media_id: 0,
	related_content : new Array(),
	jsondata : new Array(),
	pkg_id : 0,
	seg_id : 0,
	clean : function () {
		this.tp_media_id = 0;
		this.pkg_id = 0;
		this.seg_id = 0;
		this.jsondata.length = 0;
	},
	parse_video_id : function(id) { 
		this.rest_id = id;
		this.nola = id.substring(0,4);
		this.fullshow = (id.substring(7,8) == 'c' || id.substring(7,8) == 'o' || id.substring(7,8) == 'p')? true:false;
		this.brand_id = parseInt(id.substring(4,6), 16);
		if(id.substring(7,id.length).indexOf('q') != -1){
			var rem = id.substring(7,id.length).split(/q/);
			this.pkg_id = parseInt(rem[1],16);
			this.seg_id = parseInt(rem[0],16);
		} else {
			this.fullshowmode = true;
			this.pkg_id = parseInt(id.substring(7,id.length),16);
		}
		return this;
	},
	set_timer : function(t) {
	    this.timer = t;	
	},
	get_data_from_server : function(server) {
		server.getdir_fromcache(this);
		return this;
	},
	get_data_from_svc : function(server) {
		// if the above call fails (geoip blocking), the jsonpcallback will call this
		// to get data directly from the web service
		server.getdir_fromsvc(this);
		return this;
	},
	get_relc_from_server : function(server) {
		server.getrel_fromcache(this);
		return this;
	},
	get_relc_from_svc : function(server) {
	    server.getrel_fromsvc(this);
	    return this;	
	},
	load_data : function(data) {
		this.pkg_title = data.pkt;
		this.pkg_link = data.url;
		this.brand_title = data.brt;
		this.itunes_link = data.itn;
		this.embeddable = (data.emb == 1)? true:false;
		this.tp_media_id = parseInt(data.mid);
		this.progid = data.prgid;
		var haserror = false;
		if(data.error != null && data.error != ''){
			haserror = true;
			if(data.error == 'access from this location is blocked'){
				this.isblocked = true;
			}
			if(data.error == 'package requires password'){
				this.ispassword = true;
			}
		}
		if(!haserror){
			this.jsondata = data;  // let's hang onto the json so we can load the other segments
			var i, seg;
			var fauxstartmode = (data.ditems[1] != undefined && data.ditems[1].tim == 0)? true:false;
			var tim = 0;			
			for(i=0;i<data.ditems.length;i++) {
				seg = data.ditems[i];
				if(fauxstartmode){  // this is to simulate start times without removing the existing chapterized stuff
					seg.tim = tim;
					tim += seg.len;
				}
				//alert(seg.id);
				if(seg.src.indexOf('.mp4') != -1){
					this.mobilefriendly = true;
				} else {
					this.mobilefriendly = false;
				}
				if(seg.id == this.seg_id || (this.fullshowmode && i == 0)) {
					this.seg_id = seg.id;
					this.seg_title = seg.tit;
					this.seg_desc = seg.dsc;
					this.seg_length = seg.len;
					this.tmb = seg.tmb;
					this.seg_start = seg.tim;
					this.seg_end = seg.tim + seg.len;
					this.seg_link = (seg.url != '')? seg.url:this.pkg_link;
					this.video_file = seg.src;
					this.seg_index = seg.pki;
				}
			}
		}
		this.loaded = true;
		return this;
	},
	upd_chapter : function (idx) {
		for(i=0;i<this.jsondata.ditems.length;i++) {
			seg = this.jsondata.ditems[i];
			if(seg.pki == idx) {
				this.seg_id = seg.id;
				this.seg_title = seg.tit;
				this.seg_desc = seg.dsc;
				this.seg_length = seg.len;
				this.seg_link = (seg.url != '')? seg.url:this.pkg_link;
				this.tmb = seg.tmb;
				this.video_file = seg.src;
				this.seg_index = seg.pki;
			}
		}
		this.relloaded = false;
		return this;
	},
	player_type : function() {  
		//alert(this.label);
		if(this.tp_media_id == 0 || this.tp_media_id == null) {
			return "npa";
		} else {
			return "cove";
		}
	},
	mp4_enabled : function () {
		return this.mobilefriendly;
	},
	load_reldata : function(data) {
		this.related_content.length = 0;
		var relc = new Array();
		var rela = new Array();
		for(var i=0;i<data.rels.length;i++) {
			if(data.rels[i].idcode == null){
				data.rels[i].fired = false;
				relc.push(data.rels[i]);
				rela.push(data.rels[i].tim);
			}
		}
		rela.sort(function (a,b) { return a > b });
	
		for(var x = 0; x < rela.length; x++){
			for(var y = 0; y < relc.length; y++){
				if(rela[x] == relc[y].tim){
					this.related_content.push(relc[y]);
				}
			}
		}
		this.relloaded = true;
		return this;
	}
};

function jsbridge (msg){
	if(console){
		console.log(msg);
	}
}

var flp_player = {
	label : 'flp_player',
	mode : 'npa',
	receptive : false,
	chupdate_callback : null,
	htmlplayer : null,
	isinseek : false,
	currenttime : 0,
	isplaying: false,
	wasad: false,
	isready : false,
	playercode : 'npaplayer',
	chdata : {},
	waitmode : false,
    tasks : {},	
    register_task : function(evt, func) { this.add_task_to_queue(func, evt); },
    add_task_to_queue : function(func, evt) {
	    this.tasks[evt] = func;
    },
    legacy_player : function () {
		this.mode = 'npa';
		var player_code  = '<div class="player" id="npaplayer">loading</div>';
		return player_code;
    },
	legacy_player_init : function(id,w,h,ap,emb,fullshow) {
		w += 2; // compensate for skin width
		h += 32;  // compensate for control height;
		this.isready = true;
		var subthis = this;
		var config = new Array();
		this.receptive = true;
		config.pap_url = location.href;
		config.pap_ffw = w;
		config.pap_ffh = h;
		config.pap_legacymode = true;
		config.pap_hash = id;
		if(ap){
			config.pap_play = true;
		}
		if(fullshow){
			config.pap_fullshow = true;
			config.pap_arrowonly = true;
		} else {
			config.pap_fullshow = false;
			config.pap_standalone = true;
			config.pap_arrowonly = false;
		}
		if(!emb){
			config.pap_relatedexternal = true;
		} else {
			config.pap_replay = true;
		}
		config.pap_usecache = true;
		config.pap_evtmgr = this.legacy_player_evthandle;
		swfobject.embedSWF("/wgbh/pages/frontline/video/flv/e10.swf","npaplayer",w,h,"9.0.115.0",null,config, { 'wmode':'opaque', 'scale':'noscale', 'salign':'tl', 'menu':false, 'allowFullScreen':true, 'allowScriptAccess':'always' }, { id:'npap',name:'npap' });
	},
	legacy_player_evthandle : function (evt, ch) {
		if(evt == 'onPlay'){
			this.flp_player.evthandle('playing');
			this.flp_player.isplaying = true;
		}
		if(evt == 'onPause' || evt == 'onStop'){
			this.flp_player.evthandle('paused');
			this.flp_player.isplaying = false;
		}
		if(evt == 'onDone'){
			this.flp_player.evthandle('ended');
			this.flp_player.evthandle('endchapter');
			this.flp_player.isplaying = false;
		}
		if(evt == 'onChapter'){
			this.flp_player.evthandle('chapterup');
		}
	},
	cove_player : function() {
		this.mode = 'cove';
		var player_code  = '<div id="v_comms"><div id="commManagerDiv"></div></div><div id="v_coveouter"><div id="npaplayer">loading</div></div>';
		return player_code;
	},
	cove_report : function (ev) {
		if(console){
			console.log(ev);
		}
	},

	cove_player_start : function(mediaid,w,h,ap,inchdata,st,en,extemb,override) {
//		h += 18; // compensate for control height;
		this.playercode = 'npaplayer';
		swfobject.embedSWF("http://www-tc.pbs.org/video/media/swf/commManager.swf?19417", "commManagerDiv", "1", "1", "9.0.159","http://www-tc.pbs.org/video/media/swf/expressInstall.swf?19417", {}, { 'allowScriptAccess':'always', 'wmode':'transparent' }, { id: 'commManagerDiv', name: 'commManagerDiv' });
		tpSetCommManagerID("commManagerDiv",false);
		
		var fv = {};
		fv.endscreen = false;
		fv.ID = this.playercode;
		fv.allowFullScreen = true;
		fv.autoPlay = ap;
		fv.height = h;
		fv.player = this.playercode;
		fv.width = w;
		if(override){
			fv.chapterbar = false;
			fv.start = st;
			fv.end = en;
		}
		fv.video = 'http://video.pbs.org/videoPlayerInfo/' + mediaid + '/?player='+this.playercode;
		swfobject.embedSWF("http://www-tc.pbs.org/video/media/swf/PBSPlayer.swf","npaplayer",w,h,"9.0.159",null,fv, { 'wmode':'opaque', 'scale':'noscale', 'salign':'tl', 'menu':false, 'allowFullScreen':true, 'allowScriptAccess':'always' }, { id:this.playercode,name:this.playercode, bgcolor:'#000000' });

		tpRegisterID(this.playercode);

		var subthis = this;
						

		tpController.addEventListener('OnPlayerLoaded', function () { subthis.evthandle('ready'); subthis.isready = true; });
		tpController.addEventListener('OnMediaStart',function () { subthis.receptiveness(); subthis.wasad = subthis.adcheck(); });
		tpController.addEventListener('OnMediaPlay',function () { subthis.evthandle('playing'); subthis.isplaying = true; });
		tpController.addEventListener('OnMediaUnpause',function () { subthis.evthandle('playing'); subthis.isplaying = true; });
		tpController.addEventListener('OnMediaPause',function () { subthis.evthandle('paused'); subthis.isplaying = false; });
		tpController.addEventListener('OnMediaComplete',function () { if(subthis.wasad){ subthis.evthandle('endchapter'); subthis.evthandle('ended'); subthis.isplaying = false; } });
		tpController.addEventListener('OnMediaEnd',function () { if(subthis.wasad){ subthis.evthandle('endchapter'); subthis.evthandle('ended'); subthis.isplaying = false; }});
		tpController.addEventListener('OnReleaseEnd',function () { subthis.evthandle('ended'); subthis.isplaying = false; tpController.resetPlayer(); });
		tpController.addEventListener('OnLoadReleaseUrl', function () { subthis.isready = true; });
		tpController.addEventListener('OnReleaseStart', function () { subthis.isready = true; if(subthis.waitmode){ subthis.wait_stop(); } });
	
		(function (subthis){
			tpController.addEventListener('OnMediaPlaying',function(event) { subthis.cove_timeupd(event, subthis); subthis.isplaying = true; });
		}(subthis));
		
		if(!ap){
			this.isplaying = false;
		}
	},
	previous_clip : function () {
		tpController.previousClip();
	},
	cove_timeupd : function (timeobj, thing) {
		thing.currenttime = parseInt(timeobj.data.currentTime / 1000);
	},
	evthandle : function (caller) {
		if(caller != undefined){
			if(this.tasks[caller]){
				this.tasks[caller].call();
			}
		}
	},
	reset_player : function () {
		tpController.resetPlayer();
	},
	adcheck : function () {
		if(this.mode == 'cove'){
			var a;
			if(navigator.appName.indexOf("Microsoft")!=-1)
			{
			a=window[this.playercode]
			}
			else
			{
			a=document[this.playercode]
			}
			return a.adstatus();
		}
	},
	isalive : function () {
		var ret = true;
		if(this.mode == 'cove'){
			ret = false;
			var a;
			if(navigator.appName.indexOf("Microsoft")!=-1)
			{
			a=window[this.playercode]
			}
			else
			{
			a=document[this.playercode]
			}
			try { var x = a.adstatus(); ret = true; } catch (e) {
				ret = false;
			}
		}
		this.trycount = 0;
		return ret;		
	},
	html5_player : function (filen,w,h,tmb,ap) {
		this.mode = 'html5';
		if(filen.indexOf('http') == -1){
			filen = 'http://www-tc.pbs.org' + filen;
		}
		var player_code = '<video id="npavid" width="' + w + 'px" height="' + h + 'px" controls="controls"';
		player_code += (ap)? ' autoplay="true"':'';
		player_code += ' poster="' + tmb + '" src="' + filen + '"></video>';
		this.receptive = true;
		return player_code;
	},
	html5_evt : function () {
		this.htmlplayer = document.getElementById('npavid');
		var subthis = this;
		this.htmlplayer.addEventListener('ended',function () {  subthis.evthandle('endchapter'); subthis.evthandle('ended'); subthis.isplaying = false;},true);
		this.htmlplayer.addEventListener('error',function () { subthis.evthandle('error'); subthis.isplaying = false; },true);
		this.htmlplayer.addEventListener('playing',function () { subthis.evthandle('playing'); subthis.isplaying = true;  },true);
		this.htmlplayer.addEventListener('pause',function () { subthis.evthandle('paused'); subthis.isplaying = false; },true);
	},
	play : function () {
		if(this.mode == 'npa'){
			// play goes here
		} else {
			if(this.mode == 'html5'){
				this.htmlplayer.play();		
			} else {
				tpController.pause(false);
			}
		}
	},
	playchapter : function (chidx,isfirst) {
		if(this.isready){
			if(this.waitmode){
				this.wait_stop();
			}
			if(this.mode == 'cove'){
				tpController.seekToPosition(chdata[chidx]*1000);
				tpController.pause(false);
			} else {
				var a;
				if(navigator.appName.indexOf("Microsoft")!=-1)
				{
				a=window['npap']
				}
				else
				{
				a=document['npap']
				}
				a.chapterload(chidx+1,isfirst);
			}
		} else {
			var subthis = this;
			if(!this.waitmode){
				this.wait_start();
			}
			setTimeout(function () { subthis.playchapter(chidx,isfirst) }, 500);
		}
	},
	wait_start : function () {
		this.waitmode = true;
		if($("#v_embp")){
			$("#v_impatient").css({ 'margin-top': ($("#v_main").height() / 2) - 24 + 'px', 'margin-left': ($("#v_main").width() / 2) - 24 + 'px' });
		} else {
			$("#v_impatient").css({ 'margin-top': '115px', 'margin-left': '260px' });
		}
		$("#v_impatient").html('<img src="/wgbh/pages/frontline/art/v1/v_bigload.gif" width="48" height="48" alt="" />');
		$("#v_impatient").show();
		if($("#v_replacementthumb")){
			$("#v_replacementthumb").html('');
			$("#v_replacementthumb").show();
		}	
	},
	wait_stop : function () {
		this.waitmode = false;
		if($("#v_replacementthumb")){
			$("#v_replacementthumb").hide();
		}	
		$("#v_impatient").fadeOut("slow",function () {
			$("#v_impatient").html('');
			$("#v_impatient").remove();
		});
	},
	playbutton : function () {	
		if(this.mode == 'cove'){
			if(this.isready){
				if(this.waitmode){
					this.wait_stop();
				}
				tpController.pause(false);
				tpController.disablePlayerControls(false);
			} else {
				var subthis = this;
				if(!this.waitmode){
					this.wait_start();
				}
				setTimeout(function () { subthis.playbutton() }, 500);
			}
		} else {
			if(this.mode == 'npa'){
				var a;
				if(navigator.appName.indexOf("Microsoft")!=-1)
				{
				a=window['npap']
				}
				else
				{
				a=document['npap']
				}
				a.pap_play();
			} else {
				this.htmlplayer.play();
			}
		}
	},
	receptiveness : function () {
		this.receptive = true;
	},
	pause : function () {
		if(this.mode == 'cove'){
			tpController.pause(true);
		} else {
			if(this.mode == 'npa'){
				var a;
				if(navigator.appName.indexOf("Microsoft")!=-1)
				{
				a=window['npap']
				}
				else
				{
				a=document['npap']
				}
				a.pap_pause();
			} else {
				this.htmlplayer.pause();		
			}
		}
	}, 
	seek : function (seekpoint,dontplay,firsttime) {
		if(this.isready){
			isinseek = false;
			if(this.mode == 'cove'){
				var pt = parseInt(seekpoint) * 1000;
				tpController.seekToPosition(pt);
				if(!this.isplaying && !dontplay){
//					if(!firsttime){
						tpController.pause(false);
//					} else {
//						tpController.clickPlayButton();
//					}
				}
			} else {
				// so far only cove supports seek
			}
		} else {
			isinseek = true;
			var subthis = this;
			var recreload = setTimeout(function () { subthis.seek(parseInt(seekpoint)) }, 500);
		}
	},
	timerupdate : function () {
		if(this.receptive){
			// cove time management via their onmediaplaying event
			if(this.mode == 'html5'){
				this.currenttime = parseInt(this.htmlplayer.currentTime);
			}				
			if(this.mode == 'npa'){
				var a;
				if(navigator.appName.indexOf("Microsoft")!=-1)
				{
				a=window['npap']
				}
				else
				{
				a=document['npap']
				}
				var rett = a.gettime();
				this.currenttime = parseInt(rett.showtime);
			}				
		}
		return this.currenttime;
	},
	chapterswitch : function (targetfile) {
		if(targetfile.indexOf('http') == -1){
			targetfile = 'http://www-tc.pbs.org' + targetfile;
		}
		this.htmlplayer.autoplay = true;
		this.htmlplayer.src = targetfile;
		this.htmlplayer.load();
		this.htmlplayer.play();
	}
};

// flp_core
// This object is the main player object that interacts with the window
var flp_core = {
    server : null,
    label : 'flp_core',
    //playlist : new Array(),
    //playlist_index : null,
    div : 'player',	//default div to place player into
    prepare : function(vidid) {
	    this.playlist = new Array();
	    this.playlist_index = null;
	    this.server = Object.beget(flp_comm);
	    this.timer = Object.beget(flp_timer);
	    var v = Object.beget(flp_video);
	    v.set_timer(this.timer);
	    v.parse_video_id(vidid).get_data_from_server(this.server); //.get_relc_from_server(this.server, this.timer);
	    this.playlist.push(v);
	    this.playlist_index = 0;
	    this.player_module = Object.beget(flp_player);
	    this.show_when_ready();
	    return this;
    },
    show_when_ready: function() {
	    var fc = this;	    
	    window.show_when_ready = function() {
		    //alert(v.label);
		    if(fc.current_video().loaded === true) { fc.show(); }
		    else {
			    $('#'+fc.div).text("loading video player components");
		        setTimeout('window.show_when_ready()', 2000);	
	    	}
	    };
	    window.show_when_ready();
	
    },
    show : function() {
	    var v = this.current_video(); 
	    if(v.player_type() == "cove") {
		    $('#player').html(this.player_module.cove_player(v.tp_media_id,this.div));
		    this.player_module.cove_player_start(v.tp_rel_id,512,288);
	    } else { 
		    $('#player').html(this.player_module.legacy_player(v.rest_id,div,512,288));  
	    }
	    return this;
    },

    current_video : function() { 
	    if(this.playlist_index == null) { return null; }
	    else { return this.playlist[this.playlist_index]; }
	}
};

var flp_timer = {
    running_time : 0,
    loop_time : 0,
    is_running : false,
    tasks : {},
    recurring_tasks : {},
    set_time : function (newtime) {
    	timer.running_time = newtime;	
    },
    initialize_timer : function() {
	    var timer = this;
	    window.run_events = function() {
		    var now = timer.running_time;
		    if(timer.is_running) { 
			    var tstring = now.toString();
			    // handle one-off tasks
			    if(timer.tasks[tstring]) {
				    var tasks = timer.tasks[tstring];
				    for(var i=0;i<tasks.length;i++) {
					    tasks[i].func.apply(tasks[i].context, tasks[i].args);
				    }
			    }
			    // handle recurring tasks - do this outside of the play time
			    for (tstring in timer.recurring_tasks) {
				    var t = parseInt(tstring);
				    if(timer.loop_time && timer.loop_time % t == 0) {
					    var rtasks = timer.recurring_tasks[tstring];
					    for(i=0;i<rtasks.length;i++) {
						    rtasks[i].func.apply(rtasks[i].context, rtasks[i].args);
					    }
				    }
			    }
			    			   
			}
			
			timer.loop_time++;
		    
	    };
	    timer.start = function() { timer.is_running = true; };
	    timer.pause = function() { timer.is_running = false; };
	    timer.reset = function() { timer.is_running = false; timer.running_time = 0; };
	
	    setInterval("run_events()", 1000);
    }, 
    register_task : function(func, time, context, args) { this.add_task_to_queue(this.tasks, func, time, context, args); },
    register_recurring_task : function(func, interval, context, args) { this.add_task_to_queue(this.recurring_tasks, func, interval, context, args); },
    add_task_to_queue : function(q, func, time, context, args) {
	    var id = this.generate_id();
	    var t = {
		    'id' : id,
		    'func' : func,
		    'context' : context,
		    'args' : args
	    };
	    time_idx = time.toString();
	    if(q[time_idx]) {
		    q[time_idx].push(t);
	    } else {
		    q[time_idx] = [t];
	    }
	    return id;
    }, 
    generate_id : function() {
	    return 1;
    },
    remove : function(id) {
	    var tasklist, i, t;
	    for (idx in this.tasks) {   //join tasks & recurring tasks?
		    tasklist = this.tasks[idx];
		    for(i=0;i<tasklist.length; i++) {
			    t = tasklist[i];
			    if (t.id === id) { 
				    delete t.id;
				    return this;
				}
		    }
	    }
	    for (idx in this.recurring_tasks) {   //join tasks & recurring tasks?
		    tasklist = this.recurring_tasks[idx];
		    for( i=0;i<tasklist.length; i++) {
			    t = tasklist[i];
			    if (t.id === id) { 
				    delete t.id;
				    return this;
				}
		    }
	    }
    }
};

var flp_related = {
	initialize : function(reldata) {
		for(key in reldata) {
			this.key = reldata.key;
		}
	},
	show : function() {
		// code to diplay related content goes here
		return this;
	}
}



