/**
 * @author Stef Hock
 * @version 1.0
 */
if(typeof ns_API == "undefined")
    ns_API = {
    		loadEvents : [],
   			regCounter : new RegExp(/(?:https?):\/\/([^\/]+)\/([^\/]+)\/([^\/]+)\/s\?([\w_\-\.\[\]\(\)\$\~\{\}\*\^\,]{1,200})/)
   	};

if(typeof ns_API.addEvent == "undefined")
    ns_API.addEvent = (document.addEventListener) 
                                    ? (function (element, type, handler) {element.addEventListener(type, handler, false)}) 
                                    : (document.attachEvent) 
                                        ? (function (element, type, handler) {element.attachEvent("on" + type, handler)}) 
                                        : new Function;      

if(typeof ns_API.isIE == "undefined")
    ns_API.isIE = /*@cc_on!@*/false;                                        


if(typeof ns_API.isIE7 == "undefined")
	ns_API.isIE7 = (ns_API.isIE && /MSIE\s*7/i.test(navigator.userAgent)) ? true : false;

if(typeof ns_API.getJSPageURL == "undefined")
    ns_API.getJSPageURL = function () {return (document.URL) ? document.URL : document.location.domain + document.location.pathname + document.location.search};
                                        
if(typeof ns_API.onDocumentReady == "undefined")
{
    ns_API.onDocumentReady = function (func)
    {
        try
        {
            if (document.addEventListener)
            {        
                document.addEventListener("DOMContentLoaded", func, false);
            } else if (/msie/i.test(navigator.userAgent))
            {
                var id = "__ie_onload_" + new Date().getTime();
                document.write("<script id=\"ns_api_streaming" + id + "\" defer src=\"javascript:void(0)\"><\/script>");
                var script = document.getElementById(id);
                script.onreadystatechange = function() 
                {
                  if (/complete/i.test(this.readyState)) 
                    func();
                }
            } else if (/webkit/i.test(navigator.userAgent))
            {
                var _timer = setInterval(function() 
                  {        
                    if (/loaded|complete/.test(document.readyState)) 
                    {            
                      clearInterval(_timer);            
                      func();
                    }    
                 }, 10);                    
            } else
            {
                throw 0;
            }
        } catch (e) {ns_API.addEvent(window, "load", func);}
    };
}


if(typeof ns_API.addLoadEvent == "undefined")
{
    ns_API.addLoadEvent = function (func)
    {
        ns_API.loadEvents.push(func);
        if(!ns_API.loadEventHandler)
            ns_API.loadEventHandler = ns_API.onDocumentReady(function ()
                {
                    for(var i = 0,loadEvent; (loadEvent = ns_API.loadEvents[i]); i++)
                        if(loadEvent instanceof Function)
                            loadEvent()
                }
               );
    };
}
    
// BEGIN STREAMING    

if(typeof ns_API.streaming == "undefined")
{    
	ns_API.streaming = function ()
	{
		return {
		  version : "1.0.0",    
		  DEBUG : false,
		  DEVELOPER : false,
		  players : {},
		  cntPlayers : 0,
		  url : "",
		  label_prefix : "ns_st_",
		  incLogs : 0,
		  uniqueIds : {},
		  keepAliveInterval : 20, // minutes             
		  players : [],
		  
		  events : {
		    "play" : ["pb","pl","cn","pr","ep","pn","tp","el","dt","ty","br","cs","st","cl","ca","ub","bt","mp","mv","fee","id","po","sq","sp","sv","cu","li","jspageurl","er"]
		    ,"pause" : ["pl","pr","cc","ep","pn","tp","el","dt","ty","st","id","po","li","cn"]
		    ,"end" : ["pe","pl","pr","cp","cn","ep","pn","tp","el","dt","ty","br","cs","st","cl","ca","ub","bt","bp","mp","mv","fee","pt","pa","id","po","pc","pp","sv","cu","sp","li","jspageurl","er"]
		    ,"keep-alive" : "jspageurl"
		  },
		  
		  init : function ()
		  {  
		  	 try
		  	 {
		  	 	 if(this.url == "")
		  	 	 	this.url = window.ns_pixelUrl.match(ns_API.regCounter)[0];
		  	 	 	
			     for(var i = 0, player; (player = this.players[i]); i++)
			     {
			     	if(player.onInit instanceof Function)
			     	{
			     		try
			     		{
			     			player.onInit.call(player);
			     		} catch (e) {this.throwException(e)}
			     	}
			     }
		  	 } catch (e)
		  	 {
		  	 		this.throwException(e);
		  	 }
		  },
		  
		  throwException : function (e)
		  {
		  	if(this.DEBUG)
					alert("Streaming API\n" + (e.message || e));	  
		  },
		  
		  uniqueID : function ()
		  {
		    var time = new Date().getTime();
		    
		    if(!this.uniqueIds[time])
		        this.uniqueIds[time] = 0;
		
		    this.uniqueIds[time]++;
		    return String(time + "#" + this.uniqueIds[time]);                    
		  },
		  
		  setKeepAlive : function (player)
		  {
		    var _player = player;
		    var func = function () {ns_API.streaming.setKeepAlive.call(ns_API.streaming,_player);};
		    if(!player.keepalive)
		        player.keepalive = setInterval(func, this.keepAliveInterval * 6e4); // 20 minutes
		    else
		        this.log("keep-alive",{});
		  },
		  
		  enableKeepAlive : function (player)
		  {
		  	if(!player.keepalive) this.setKeepAlive(player);	
		  },
		  		  
		  clearKeepAlive : function (player)
		  {
		    if(player && player.keepalive)
		        clearInterval(player.keepalive);
		  },
		  
		  log : function (ev, labels)
		  {
        if(!labels)
            return;
                
		  	try
		  	{
		  		if(this.url == "")
		  			throw "Please specify a valid sitestat url";
		  			
		  	  var qs = ["&" + this.label_prefix + "ev=" + ev, "ns_type=hidden","ns_ts=" + new Date().getTime()];
		 
			    if(!this.events[ev])
			        return;

			    var regex = new RegExp();
			    for(var label in labels)
			    {
			        regex.compile(label, "i");
              if((labels[label] != "" || labels[label] == 0) && labels[label] != null && typeof labels[label] != "undefined" && (regex.test(this.events[ev])))
			        {
                if(/cu/i.test(label))
		                qs = qs.concat(labels[label].split("&"));
		            else
		                qs.push(  (/jspageurl/i.test(label)  ? "ns_jspageurl=" + escape(labels[label]) : this.label_prefix + label + "=" + String(escape(labels[label]).substring(0,200))));   
			        }
			    }
			    // LOGGING
			    window["ns_img" + this.incLogs] = new Image();
			    window["ns_img" + this.incLogs].src = this.url + qs.join("&");

			    if(this.DEVELOPER)
			    {
			    	if(this.debugLabels)
			    	{
			    		var arr = [];
			    		for(var j = 0; j < qs.length; j++)
			    		{
			    			if(this.debugLabels.test(qs[j]))
			    				arr.push(qs[j]);
			    		}
			    		qs = arr;			    			
			    	}
			    	document.getElementById("debug").innerHTML = "<HR>" + qs.sort().join("&")
			    																													.replace(/ns_(type|ts)\=[^&]+&/gi,"")
			    																													.replace(/\=(play|pause|end)/gi,"=<font color='blue'>$1</font>")
			    																													.replace(/(ns_st_[^\=]+)\=([^&]+)/gi,"<font color='red'>$1</font>=<b>$2</b>")
			    																													.substring(1).replace(/&/g,"<br/>") + document.getElementById("debug").innerHTML;
			    }
			    this.incLogs++;
		  	} 
		  	catch (e) {this.throwException(e)}
		  },
		  
		  getURL : function () { return this.url;},
		  setURL : function (_url) {this.url = _url;},
		  
		  register : function (player)
		  {
		    this.players.push(player);
		  },
		  
			_construct : ns_API.addLoadEvent(function () { ns_API.streaming.init.apply(ns_API.streaming)}) 
		}
	}();
};

// PLAYLIST

ns_API.streaming.playlist = function ()
{
	this.entries = [];
	this.uid = ns_API.streaming.uniqueID();
	this.sequence = 1;
};


/**
 * @param {ns_API.streaming.playlistItem} entry
 */
ns_API.streaming.playlist.prototype.addEntry = function (entry)
{
  this.entries.push(entry)
  entry.uid = this.uid;
  entry.clip = this.entries.length;
};

/**
 * @param {String} key
 * @type Mixed
 */
ns_API.streaming.playlist.prototype.getTotalValues = function (key)
{
  var total = 0, value;
  for(var i = 0, entry; (entry =this.entries[i]); i++)
  {
  		value = /duration/i.test(key) ? entry["info"][key] : entry[key];
  		
      total += (value == "undefined" || isNaN(parseInt(value)) ? 0 : parseInt(value));             
  }
  return total;                    
};

/**
 * @type Long
 */
ns_API.streaming.playlist.prototype.getTotalPlayingTime = function () { return this.getTotalValues("totalPlayed");};
/**
 * @type Integer
 */
ns_API.streaming.playlist.prototype.getTotalEvents = function () { return this.getTotalValues("events");};
/**
 * @type Long
 */
ns_API.streaming.playlist.prototype.getPlayListLength = function () { return this.getTotalValues("duration");};
/**
 * @type Long
 */
ns_API.streaming.playlist.prototype.getTotalBufferTime = function ()
{
  var total = 0;
  for(var i = 0, entry; (entry = this.entries[i]); i++)
      total += entry.getBufferTime();             
  return total;        
};

// PLAYLIST ENTRY

/**
 * @param {Object} options
 */
ns_API.streaming.playlistItem = function (options)
{
	options = options || {};
  this.uid = 0;                   
  this.sequence = 0;
  this.buffer = [];
  this.__bufferstart = 0;
  this.currentPosition = 0;
  this.events = 0;
  this.playStart = 0;
  this.totalPlayed = 0;
  this.playTime = 0;
  this.episodeLength = options.episodeLength || 0;
  this.clip = options.clip || 1;
  this.info = {
			date : options.date,
  		duration : (options.duration) ? options.duration == "" ? 0 : options.duration : 0,	
			station : options.station,
			streamtype : options.streamtype,
			totalparts : options.totalparts || 1,
  		fee : options.fee,	
			part : options.part || 1,
			episode : options.episode || 1,
			program : options.program,
			custom : options.custom || ""  
  };
  
  this.playing = false;
  this.paused = false;
  this.buffering = false;
  this.timer = null;
  this.onPlayingCallback = options.onPlayingCallback; 
};

ns_API.streaming.playlistItem.prototype.clear = function ()
{
	this.buffer = [];
	this.events = 0;
	this.playStart = 0;
	this.playTime = 0;
	this.totalPlayed = 0;
};

/**
 * @param {ns_API.streaming.player} player
 */

ns_API.streaming.playlistItem.prototype.play = function (player) 
{
	if(this.buffering)
		this.bufferEnd();

	if(this.playing)
		return;

	this.playStart = new Date().getTime();	
	var scope = this;
	this.timer = window.setInterval(function () {try{scope.onPlaying.call(scope)}catch(e){}}, 100);
	
	this.playing = true;	
	this.paused = false;
	ns_API.streaming.enableKeepAlive(this);
};

/**
 * @param {ns_API.streaming.player} player
 */
ns_API.streaming.playlistItem.prototype.pause = function (player)
{
	this.events++;
	this.paused = true;
	if(this.timer)
		window.clearInterval(this.timer);
	this.playing = false;	
};

/**
 * @param {ns_API.streaming.player} player
 */
ns_API.streaming.playlistItem.prototype.end = function (player)
{
  if(!this.playing && this.playing != null)
      return;
	ns_API.streaming.clearKeepAlive(this);
	if(this.timer)
		window.clearInterval(this.timer);
	this.playing = false;	
	this.paused = false;
};

ns_API.streaming.playlistItem.prototype.onPlaying = function ()
{
 if(this.onPlayingCallback instanceof Function)
   this.currentPosition = this.onPlayingCallback();	
};

ns_API.streaming.playlistItem.prototype.addPlayingTime = function ()
{
	this.totalPlayed += (new Date().getTime() - this.playStart);
	this.playStart = new Date().getTime();  
};

/**
 * @param {ns_API.streaming.player} player
 */
ns_API.streaming.playlistItem.prototype.bufferStart = function (player)
{
	  if(this.playing)
    {
        this.addPlayingTime();
        player.dispatchState("end", this);
        this.playing = false;        
    		this.buffering = true;            
    }
    this.__bufferstart = new Date().getTime()      
};

/**
 * @param {ns_API.streaming.player} player
 */
ns_API.streaming.playlistItem.prototype.bufferEnd = function (player)
{
	this.buffering = false;
	if(this.__bufferstart && parseInt(this.__bufferstart) > 0)
		this.buffer.push(new Date().getTime() - this.__bufferstart);
};

/**
 * @type Long
 */
ns_API.streaming.playlistItem.prototype.getBufferTime = function ()
{
	var buffer = 0;
	for(var i = 0; i < this.buffer.length; i++)
	    buffer += parseInt(this.buffer[i]);
	return buffer;
};

/**
 * @param {String} _key
 * @type Mixed
 */
ns_API.streaming.playlistItem.prototype.getItemInfo = function(_key)
{
  if(this.info[_key])
    return this.info[_key];
};

/**
 * @param {String} _key
 * @param {String} _value
 */
ns_API.streaming.playlistItem.prototype.setItemInfo = function (_key, _value)
{
  if(typeof _value != "undefined" && _value != "")
    this.info[_key] = _value;
};   

// PLAYER

ns_API.streaming.player = function (ref)
{
  this._base = ns_API.streaming; 	
	this.ref = ref;
  this.keepalive = null;
	this.player = null;
	this.playerVersion = "x.x";
  
  this.userPlaylist = {title : "", clips : []};	
	this.playLists = {};
	this.playList = null;
	
  this.classId = null;
  this.hasPlaylist = false;
  this.embedType = null;
  this.currentItem = null;
  
  this.doPlaylistEndEvent = false;
  this.doPlaylistStartEvent = true;
  if(arguments.callee.caller)
		this.construct();
};

ns_API.streaming.player.prototype.construct = function ()
{
   this._base.register(this);
};

ns_API.streaming.player.prototype.onInit = function ()
{	
	this.player = (typeof this.ref == "string") 
										?	((document.getElementById(this.ref) != null) 
											? document.getElementById(this.ref) : (window[this.ref]) ? window[this.ref] : document[this.ref]) 
										: this.ref;
	if(!ns_API.isIE && this.player && !/embed/i.test(this.player.tagName))
		this.player = document[this.player.getElementsByTagName("embed")[0].name];
	
  if(!this.player || !this.player.tagName) throw ("DomElement not found");
};

ns_API.streaming.player.prototype.clearPlaylist = function ()
{
	this.playList = null;
	this.userPlaylist = {title : "", clips : []};	
	this.playLists = {};
};


/**
 * @param {String} state
 * @param {ns_API.streaming.player} player
 * @type Mixed
 */
ns_API.streaming.player.prototype.getLabelValues = function (state, player)
{
	var obj = {};
	if(ns_API.streaming.events[state])
	{
		var labels = ns_API.streaming.events[state];
		for(var i = 0, label;(label = labels[i]); i++)
			if(this["getLabelValue_" + label.toUpperCase()] instanceof Function)
				obj[label] = this["getLabelValue_" + label.toUpperCase()]();
	}
	return obj;
};


/**
 * @param {String} state
 * @param {ns_API.streaming.playlistItem} entry
 */
ns_API.streaming.player.prototype.dispatchState = function(state, entry)
{
	if(!entry || !entry[state] instanceof Function)
		return;
	
	if(entry && entry.buffering && entry.bufferEnd instanceof Function)
		entry.bufferEnd();

	if(entry.playing)
  	entry.addPlayingTime(); 

	if((state == "end" && (entry.playing == null) || entry.playing || (entry.paused && state != "pause")) || state != "end") this._base.log(state, this.getLabelValues(state));	
       
  entry[state].call(entry, this);
	this.doPlaylistStartEvent = false;     
 };


/**
 * @param {String} state
 */
ns_API.streaming.player.prototype.onOpenStateChange = function (state)
{
  if(this["onOpenState_" + this.openStates[state]] instanceof Function)
      this["onOpenState_" + this.openStates[state]].apply(this, arguments);                              
};

/**
 * @param {String} state
 */
ns_API.streaming.player.prototype.onPlayStateChange = function (state)
{
  if(this["onPlayState_" + this.playStates[state]] instanceof Function)
      this["onPlayState_" + this.playStates[state]].apply(this, arguments);
};


/**
 * @param {Boolean} start
 */
ns_API.streaming.player.prototype.onBuffering = function(start)
{
	var entry = this.getSelectedItem();
	if(!entry)
		return;
	entry["buffer" + ((start) ? "Start" : "End")](this);
};


/**
 * @param {String} durationString
 * @type Long
 */
ns_API.streaming.player.prototype.getDurationFromString = function (durationString)
{
	var arr = durationString.split(":"),duration = 0;
	for(var i = arr.length - 1, j = 0; i >= 0; i--, j++)
		duration += isNaN(parseInt(arr[i])) ? 0 : parseInt(arr[i]) * (Math.pow(60,j) * 1000);
	return duration;
};

/**
 * @param {String} a_title
 */
ns_API.streaming.player.prototype.setPlaylistTitle = function(a_title)
{
	this.userPlaylist.title = a_title;
};

/**
 * @param {Integer} a_clip_nr
 * @param {String} a_duration
 * @param {String} a_program
 * @param {String} a_episode
 * @param {Integer} a_totalparts
 * @param {Integer} a_part
 * @param {String} a_date
 * @param {String} a_fee
 * @param {String} a_station
 * @param {String} a_streamtype
 * @param {String} a_custom
 */
ns_API.streaming.player.prototype.setClipDetails = function (a_clip_nr, a_duration, a_program, a_episode, a_totalparts, a_part, 
																															a_date, a_fee, a_station, a_streamtype, a_custom) 
/* 
* String clip_nr, String duration String program, String episode, 
* Integer totalparts, Integer part, String fee, 
* String station, String streamtype, String custom
*/
{
	a_clip_nr = (a_clip_nr && !isNaN(parseInt(a_clip_nr))) ? parseInt(a_clip_nr) : 1;
	if(!this.userPlaylist.clips) this.userPlaylist.clips = [];
	if(this.userPlaylist.clips.length < a_clip_nr) this.userPlaylist.clips.length = a_clip_nr;
	
	this.userPlaylist.clips[a_clip_nr - 1] = new this._base.playlistItem({
			clip : a_clip_nr,
			duration : a_duration,
			date : a_date,
      station : a_station,
      streamtype : a_streamtype,
      totalparts : a_totalparts,
      part : a_part,
      episode : a_episode,
      program : a_program,
      custom : a_custom
  	});
};

/**
 * @param {String} key
 * @param {Integer} clip_nr
 * @param {ns_API.streaming.playlistItem} entry
 * @param {Function} callback
 */
ns_API.streaming.player.prototype.getClipInfo = function (key, clip_nr, entry, callback)
{
	if(this.userPlaylist && this.userPlaylist.clips && this.userPlaylist.clips[clip_nr])
			return (callback instanceof Function) ? callback(this.userPlaylist.clips[clip_nr].getItemInfo(key)) : this.userPlaylist.clips[clip_nr].getItemInfo(key);
	else if(entry && entry.getItemInfo instanceof Function)
			return entry.getItemInfo(key);
};


/**
 * @param {Integer} clip_nr
 * @type ns_API.streaming.playlistItem
 */
ns_API.streaming.player.prototype.getPlaylistClip = function (clip_nr)
{
	if(this.userPlaylist && this.userPlaylist.clips && this.userPlaylist.clips[clip_nr])
		return this.userPlaylist.clips[clip_nr]
};

/**
 * @param {ns_API.streaming.playlist} playlist 
 */
ns_API.streaming.player.prototype.clearClipIncrements = function (playlist)
{
	for(var i = 0, entry; (entry = playlist.entries[i]); i++)
		entry.clear();
};

ns_API.streaming.player.prototype.incrementPlaylist = function ()
{
	var playlist = this.getCurrentPlaylist();
	this.clearClipIncrements(playlist);
	playlist.sequence++;
};

/**
 * @type ns_API.streaming.playlist
 */
ns_API.streaming.player.prototype.getCurrentPlaylist = function () {};
/**
 * @return begin of playlist
 * @type Boolean
 */
ns_API.streaming.player.prototype.getLabelValue_PB = function () {return (this.doPlaylistStartEvent) ? 1 : null};
/**
 * @return end of playlist
 * @type Boolean 
 */
ns_API.streaming.player.prototype.getLabelValue_PE = function () {return (this.doPlaylistEndEvent) ? 1 : null};
/**
 * @type String
 * @return type of mediaplayer
 */
ns_API.streaming.player.prototype.getLabelValue_MP = function () {return this.type};
/**
 * @type String
 * @return version of mediaplayer
 */
ns_API.streaming.player.prototype.getLabelValue_MV = function () {return this.playerVersion};
/**
 * @type String
 * @return script version
 */
ns_API.streaming.player.prototype.getLabelValue_SV = function () {return this._base.version};
/**
 * @type Long
 * @return episode length
 */
ns_API.streaming.player.prototype.getLabelValue_EL = function () {return this.getSelectedItem().episodeLength};
/**
 * @type Integer
 * @return index of current clip
 */
ns_API.streaming.player.prototype.getLabelValue_CN = function () {return this.getSelectedItem().clip};            
/**
 * @type Long
 * @return total playtime of current clip
 */
ns_API.streaming.player.prototype.getLabelValue_PT = function () {return this.getSelectedItem().totalPlayed};          
/**
 * @type Integer
 * @return total events of current clip
 */  
ns_API.streaming.player.prototype.getLabelValue_PC = function () {return this.getSelectedItem().events};
/**
 * @type Integer
 * @return sequence of current clip
 */
ns_API.streaming.player.prototype.getLabelValue_SQ = function () {var entry = this.getSelectedItem();entry.sequence = Math.max(1, entry.sequence);return entry.sequence};  
/**
 * @type Long
 * @return position in current clip
 */
ns_API.streaming.player.prototype.getLabelValue_PO = function () {return this.getSelectedItem().currentPosition};          
/**
 * @type Long
 * @return duration of current clip
 */
ns_API.streaming.player.prototype.getLabelValue_CL = function () {return this.getClipInfo("duration", this.getIndex(), this.getSelectedItem(), this.getDurationFromString)};
/**
 * @type Long
 * @return buffer time in total of current clip in milliseconds
 */
ns_API.streaming.player.prototype.getLabelValue_BT = function () {return this.getSelectedItem().getBufferTime()};
/**
 * @type String
 * @return program name
 */
ns_API.streaming.player.prototype.getLabelValue_PR = function () {return this.getClipInfo("program", this.getIndex(), this.getSelectedItem())};
/**
 * @type String
 * @return episode name
 */
ns_API.streaming.player.prototype.getLabelValue_EP = function () {return this.getClipInfo("episode", this.getIndex(), this.getSelectedItem())};
/**
 * @type Integer
 * @return part number of episode
 */
ns_API.streaming.player.prototype.getLabelValue_PN = function () {return this.getClipInfo("part", this.getIndex(), this.getSelectedItem())};
/**
 * @type String
 * @return date of clip
 */
ns_API.streaming.player.prototype.getLabelValue_DT = function () {return this.getClipInfo("date", this.getIndex(), this.getSelectedItem())};
/**
 * @type String
 * @return fee of clip
 */
ns_API.streaming.player.prototype.getLabelValue_FEE = function () {return this.getClipInfo("fee", this.getIndex(), this.getSelectedItem())};
/**
 * @type String
 * @return type of stream
 */
ns_API.streaming.player.prototype.getLabelValue_TY = function () {return this.getClipInfo("streamtype", this.getIndex(), this.getSelectedItem())};
/**
 * @type String
 * @return station name
 */
ns_API.streaming.player.prototype.getLabelValue_ST = function () {return this.getClipInfo("station", this.getIndex(), this.getSelectedItem())};
/**
 * @type Integer
 * @return total parts of episode
 */
ns_API.streaming.player.prototype.getLabelValue_TP = function () {return this.getClipInfo("totalparts", this.getIndex(), this.getSelectedItem())};
/**
 * @type String
 * @return playlist identifier of clip
 */
ns_API.streaming.player.prototype.getLabelValue_ID = function () {return this.getSelectedItem().uid};
/**
 * @type Integer
 * @return sequence of playlist
 */
ns_API.streaming.player.prototype.getLabelValue_SP = function () {return this.getCurrentPlaylist().sequence};
/**
 * @type Long
 * @return clip length of all clips
 */
ns_API.streaming.player.prototype.getLabelValue_CA = function () {return (this.doPlaylistEndEvent) ? this.getCurrentPlaylist().getPlayListLength() : null};            
/**
 * @type Long
 * @return buffer time total of all clips combined playlist in milliseconds
 */
ns_API.streaming.player.prototype.getLabelValue_BP = function () {return (this.doPlaylistEndEvent) ? this.getCurrentPlaylist().getTotalBufferTime() : null};
/**
 * @type Long
 * @return total play time of all clips combined in milliseconds
 * 
 */
ns_API.streaming.player.prototype.getLabelValue_PA = function () {return (this.doPlaylistEndEvent) ? this.getCurrentPlaylist().getTotalPlayingTime() : null};
/**
 * @type Integer
 * @return total pauses in playlist
 */
ns_API.streaming.player.prototype.getLabelValue_PP = function () {return (this.doPlaylistEndEvent) ? this.getCurrentPlaylist().getTotalEvents() : null};
/**
 * @type Integer
 * @return total clips in playlist
 */
ns_API.streaming.player.prototype.getLabelValue_CP = function () {return this.getCurrentPlaylist().entries.length};
/**
 * @type String
 * @return title of playlist
 */
ns_API.streaming.player.prototype.getLabelValue_PL = function () {return (this.userPlaylist.title.replace(/\s/g,"") != "") ? this.userPlaylist.title : null};
/**
 * @type String
 * @return URI of current page
 */
ns_API.streaming.player.prototype.getLabelValue_JSPAGEURL = function () {return ns_API.getJSPageURL()};
/**
 * @type Long
 * @return user bandwidth
 */
ns_API.streaming.player.prototype.getLabelValue_UB = function () {};
/**
 * @type String
 * @return dimensions of clip width * height
 */
ns_API.streaming.player.prototype.getLabelValue_CS = function () {};
/**
 * @type Long
 * @return bitrate of current clip
 */
ns_API.streaming.player.prototype.getLabelValue_BR = function () {};
/**
 * @type String
 * @return last known error message
 */
ns_API.streaming.player.prototype.getLabelValue_ER = function () {};
/**
 * @type Boolean
 * @return live stream
 */
ns_API.streaming.player.prototype.getLabelValue_LI = function () {};


// MEDIAPLAYER


ns_API.streaming.mediaPlayer = function () {
	this._super.apply(this, arguments);
	this.type = "MediaPlayer";
	this.classId = new RegExp(/6BF52A52-394A-11D3-B153-00C04F79FAA6/i);
	this.embedType = "";
  this.openStates = ["undefined","PlaylistChanging","PlaylistLocating","PlaylistConnecting","PlaylistLoading",
            "PlaylistOpening","PlaylistOpenNoMedia","PlaylistChanged","MediaChanging","MediaLocating",
            "MediaConnecting","MediaLoading","MediaOpening","MediaOpen","BeginCodecAcquisition","EndCodecAcquisition",
            "BeginLicenseAcquisition","EndLicenseAcquisition","BeginIndividualization","EndIndividualization","MediaWaiting","OpeningUnknownUrl"];
    
  this.playStates = ["undefined","Stopped","Paused","Playing","ScanForward","ScanReverse","Buffering","Waiting","MediaEnded","Transitioning","Ready","Reconnecting"];	
};
ns_API.streaming.mediaPlayer.prototype = new ns_API.streaming.player;
ns_API.streaming.mediaPlayer.prototype._super = ns_API.streaming.player;
ns_API.streaming.mediaPlayer.prototype.constructor = ns_API.streaming.mediaPlayer;

ns_API.streaming.mediaPlayer.prototype.onInit = function ()
{
	this._super.prototype.onInit.call(this);
	if(!ns_API.isIE)
		throw "Internet Explorer needed";
	if(!this.classId.test(this.player.classid))
		throw "Invalid classid for element\nrequired:" + this.classId.toString();	


	if(this._base.DEBUG)
		this.player.settings.mute = true;
	this.playerVersion = this.player.versionInfo;
	this.setEventHandlers();
};

ns_API.streaming.mediaPlayer.prototype.setEventHandlers = function ()
{
  var scope = this;
  this.player.SendPlayStateChangeEvents = 1;
  this.player.SendOpenStateChangeEvents = 1;
  this.player.attachEvent("PositionChange", function () {try { scope.onPositionChange.apply(scope,arguments) } catch (e) {}});
  this.player.attachEvent("PlayStateChange", function () {try { scope.onPlayStateChange.apply(scope, arguments) } catch (e) {}});
  this.player.attachEvent("OpenStateChange", function () {try { scope.onOpenStateChange.apply(scope, arguments) } catch (e) {}});
  this.player.attachEvent("buffering", function () {try { scope.onBuffering.apply(scope, arguments)   } catch (e) {}});
};

ns_API.streaming.mediaPlayer.prototype.initPlaylist = function ()
{
	var playlist = this.player.currentPlaylist, scope = this;
	if(!this.playLists[playlist.name])
		this.playLists[playlist.name] = new this._base.playlist();
    
  for(var i = 0, entry, playlistitem; i < playlist.count && (entry = playlist.item(i)); i++)
  {
  	if(this.playLists[this.player.currentPlaylist.name].entries[i])
  	{
  		this.playLists[this.player.currentPlaylist.name].entries[i].setItemInfo("duration", this.calculateDuration(entry));
  	}
  	else
  	{
	  	playlistitem = new ns_API.streaming.playlistItem(
	  		{
	  			onPlayingCallback : function () { return Math.floor(scope.player.controls.currentPosition) * 1000},
	        episodeLength : this.getEpisodeLength(entry),
	        clip : i + 1,
	        duration : this.calculateDuration(entry),
	        date : entry.getItemInfo("date"),
	        station : entry.getItemInfo("station"),
	        streamtype : entry.getItemInfo("streamtype"),
	        totalparts : entry.getItemInfo("totalparts"),
	        fee : entry.getItemInfo("fee"),
	        part : entry.getItemInfo("part"),
	        episode : entry.getItemInfo("episode"),
	        program : entry.getItemInfo("program"),
	        custom : entry.getItemInfo("custom")          		
	  		});
	  	playlistitem.uid = this.playLists[this.player.currentPlaylist.name].uid
			this.playLists[playlist.name].addEntry(playlistitem);  
  	}
  }
};


/**
 * @param {ns_API.streaming.playlistItem} _entry
 * @type Long
 */
ns_API.streaming.mediaPlayer.prototype.getEpisodeLength = function (_entry)
{
	var episode = _entry.getItemInfo("episode");
	if(episode == "")
		return this.calculateDuration(_entry);

	var total = 0;
	for(var i = 0, entry; i < this.player.currentPlaylist.count && (entry = this.player.currentPlaylist.item(i)); i++)
		if(entry.getItemInfo("episode") == episode)
			total += this.calculateDuration(entry);
	return (total == 0) ? null : total;
};

/**
 * @param {ns_API.streaming.playlistItem} entry
 * @type Long
 */
ns_API.streaming.mediaPlayer.prototype.calculateDuration = function (_entry)
{
	if(!_entry)
		return 0;
	else
		return parseFloat((_entry.getItemInfo("Duration") == "") ? 0 : _entry.getItemInfo("Duration").replace(",","."))*1000;
};

/**
 * @see ns_API.streaming.player#getLabelValue_UB
 */
ns_API.streaming.mediaPlayer.prototype.getLabelValue_UB = function () 
{
	return this.player.network.bandWidth; // returns in bits not in Kb as supposed by the API documentation of WMP
};

/**
 * @see ns_API.streaming.player#getLabelValue_PL
 */
ns_API.streaming.mediaPlayer.prototype.getLabelValue_PL = function () 
{
	
		if(this.userPlaylist.title.replace(/\s/g,"") != "")
		{
			return this.userPlaylist.title;
		}
		else
		{
			var title = this.player.currentPlaylist.getItemInfo("playlist");
			try
			{
				return (/^\s*$/.test(title)) ? null : title;
			} catch (e){}
		}
};

/**
 * @see ns_API.streaming.player#getLabelValue_CS
 */
ns_API.streaming.mediaPlayer.prototype.getLabelValue_CS = function () 
{
	try
	{
		return String(this.player.currentMedia.imageSourceWidth + "x" + String(this.player.currentMedia.imageSourceHeight));
	} catch (e) {}
};

/**
 * @see ns_API.streaming.player#getLabelValue_BR
 */
ns_API.streaming.mediaPlayer.prototype.getLabelValue_BR = function () 
{
	try
	{
		return this.player.currentMedia.getItemInfo("Bitrate");
	} catch (e) {}
};


/**
 * @see ns_API.streaming.player#getLabelValue_ER
 */
ns_API.streaming.mediaPlayer.prototype.getLabelValue_ER = function () 
{
    return (this.player && this.player.currentMedia && this.player.currentMedia.error) ? this.player.currentMedia.error.errorDescription : null;
};

ns_API.streaming.mediaPlayer.prototype.onPositionChange = function ()
{
	this.getSelectedItem().currentPosition = Math.floor(this.player.controls.currentPosition * 1000);
};

ns_API.streaming.mediaPlayer.prototype.onPlayStateChange = function (state)
{
	if(state == 1) // stopped
			this.doPlaylistEndEvent = true;

	this._base.player.prototype.onPlayStateChange.apply(this, arguments);
};


/**
 * @type ns_API.streaming.playlistItem
 */
ns_API.streaming.mediaPlayer.prototype.getSelectedItem = function ()
{
  try
  {
  	var currentPlaylist = this.player.currentPlaylist;
    var playlist = this.playLists[currentPlaylist.name]; 
    if(!playlist)
    	this.initPlaylist();
    playlist = this.playLists[currentPlaylist.name];
	  
	  for(var i = 0, entry; i < currentPlaylist.count && (entry = currentPlaylist.item(i)); i++) 
        if(this.player.currentMedia.isIdentical(entry))
            return playlist.entries[i];
  } catch (e) { return this.currentItem}
};

/**
 * @return index of current clip in playlist
 * @type Integer
 */
ns_API.streaming.mediaPlayer.prototype.getIndex = function ()
{
  try
  {
  	var currentPlaylist = this.player.currentPlaylist,
  			playlist = this.playLists[currentPlaylist.name]; 
    if(!playlist) this.initPlaylist();
    playlist = this.playLists[currentPlaylist.name];
	  
	  for(var i = 0, entry; i < currentPlaylist.count && (entry = currentPlaylist.item(i)); i++) 
        if(this.player.currentMedia.isIdentical(entry))
            return i;
  } catch (e) { return 0;}
};

/**
 * @type ns_API.streaming.playlist
 */
ns_API.streaming.mediaPlayer.prototype.getCurrentPlaylist = function ()
{
	try
	{
		return this.playLists[this.player.currentPlaylist.name];
	} catch (e) {}
};

ns_API.streaming.mediaPlayer.prototype.onPlayState_Playing = function()
{
	this.getSelectedItem().currentPosition = Math.floor(this.player.controls.currentPosition * 1000);
	this.dispatchState("play",this.getSelectedItem());
}

ns_API.streaming.mediaPlayer.prototype.onPlayState_Paused = function ()
{
	this.dispatchState("pause", this.getSelectedItem());
};

ns_API.streaming.mediaPlayer.prototype.onPlayState_Stopped = function ()
{
	var entry = this.getSelectedItem();
	this.doPlaylistEndEvent = true;
	this.dispatchState("end", entry);
	this.incrementPlaylist();
	this.doPlaylistEndEvent = false;
	this.doPlaylistStartEvent = true;	
};

ns_API.streaming.mediaPlayer.prototype.onOpenState_MediaChanging = function ()
{
  this.setEndEventState(this.currentItem);	
	this.dispatchState("end", this.currentItem);
};

ns_API.streaming.mediaPlayer.prototype.setEndEventState = function (entry)
{
  if(entry.clip == this.getCurrentPlaylist().entries.length) 
		this.doPlaylistEndEvent = true;
};


ns_API.streaming.mediaPlayer.prototype.onPlayState_MediaEnded = function ()
{
  var entry = this.getSelectedItem();
  this.setEndEventState(entry);
  this.dispatchState("end", entry);
  if(this.doPlaylistEndEvent)
 		this.incrementPlaylist();

};

ns_API.streaming.mediaPlayer.prototype.onOpenState_MediaOpen = function ()
{
  this.initPlaylist();
  var entry = this.getSelectedItem();
  entry.sequence++;
  this.currentItem = entry;
  this.doPlaylistEndEvent = false;
  entry.events = 0;
  entry.totalPlayed = 0;
  entry.playing = null;	
  entry.buffering = false;
  if(entry.clip == 1)
  	this.doPlaylistStartEvent = true;
}; 

/**
 * In Netscape version 4.x, 
 * when the parameter NOJAVA is set to true, scripting is unavailable. 
 * Setting the NOJAVA parameter in Netscape 6.0 has no effect. 
 */

ns_API.streaming.realPlayer = function () {
	this.version = "1.0.0";  
	this._super.apply(this, arguments);
	this.type = "RealPlayer";
	this.playStates = ["Stopped","Contacting","Buffering","Playing","Paused","Seeking"];
	this.classId = new RegExp(/CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA/i);
	this.embedType = "";	
	this.realTag = "object";
	this.bufferState = -1;
	this.doClipEndEvent = false;
};

ns_API.streaming.realPlayer.prototype = new ns_API.streaming.player;
ns_API.streaming.realPlayer.prototype._super = ns_API.streaming.player;
ns_API.streaming.realPlayer.prototype.constructor = ns_API.streaming.realPlayer;


ns_API.streaming.realPlayer.prototype.onInit = function ()
{
	this._super.prototype.onInit.call(this);
	try
	{
		if(!this.classId.test(this.player.classid)) 
			throw "Invalid classid for element\nrequired:" + this.classId.toString();	
		this.realTag = "object";	
	} catch (e)
	{
		// test for embed
		this.realTag = "embed";
	}
	this.setEventHandlers();
};

ns_API.streaming.realPlayer.prototype.setEventHandlers = function ()
{
	try
	{
		var scope = this;

		if(/object/i.test(this.realTag) && ns_API.isIE)
		{
            if(ns_API.isIE7)
            {
                var lastState;
                var func = function () 
                {
                    var newState = scope.player.GetPlayState();

                    if(newState  != lastState)
                    {
                    		try
                    		{
	                        if(/seeking/i.test(scope.playStates[newState]))
	                        {    
	                            scope.onClipClosed.call(scope);
	                        }
	                        else if(/buffering/i.test(scope.playStates[newState]))
	                        {
	                            scope.onBuffering.call(scope, 0);
	                        }
	                        else if(/contacting/i.test(scope.playStates[newState]))
	                            scope.onClipOpened.call(scope);
	                        else
	                        {
	                        		if(/buffering/i.test(scope.playStates[lastState]))
	                        			scope.onBuffering.call(scope, 2);                        
	                            scope.onPlayStateChange.call(scope, newState);
	                        }
                    		} catch (e) {}
                    }
                    lastState = scope.player.GetPlayState();
                };
                setInterval(func,50);
            }
            else
            {
			    			this.player.attachEvent("onPostSeek", function () { try { scope.onPostSeek.apply(scope, arguments) } catch (e) {}});
			          this.player.attachEvent("onClipOpened",  function () { try { scope.onClipOpened.apply(scope, arguments) } catch (e) {}}); 
			          this.player.attachEvent("onBuffering",  function () { try { scope.onBuffering.apply(scope, arguments)} catch (e) {}}); 
			          this.player.attachEvent("onPlayStateChange",  function () { try { scope.onPlayStateChange.apply(scope, arguments)} catch (e) {}}); // activex only receives the new state
			          this.player.attachEvent("onClipClosed",  function () { try { scope.onClipClosed.apply(scope, arguments)} catch (e) {}});  
            }   
        }
		else
		{
				// firefox
    		var name = this.player.getAttribute("name");
                
    	    window[name + "_onPostSeek"]  = function () { try { scope.onPostSeek.apply(scope, arguments) } catch (e) {}};
    			window[name + "_OnBuffering"]  = function () { try { scope.onBuffering.apply(scope, arguments)} catch (e) {}};
          window[name + "_OnPlayStateChange"] = function () { try { scope.onPlayStateChange.call(scope, arguments[1])} catch(e) {}}; // firefox sends both old and newstate we need the new state
          window[name + "_onClipOpened"] = function () { try { scope.onClipOpened.apply(scope, arguments)} catch (e) {}};
          window[name + "_onClipClosed"] = function () { try { scope.onClipClosed.apply(scope, arguments)} catch (e) {}};
		}
		ns_API.addEvent(window, "beforeunload", function () { try { scope._base.clearKeepAlive();scope.onClipClosed.apply(scope)} catch (e) {}});			
	} catch (e) {throw e.message || e;}
};

ns_API.streaming.realPlayer.prototype.initPlayList = function ()
{
	if(!this.playList) 
	{
		this.playList = new this._base.playlist();
  	this.doPlaylistStartEvent = true;		
	} else if(this.playList && this.playList.entries > 0 && this.playList.entries.length == this.player.GetNumEntries()) 
	{
			
		return;	
	}

  var scope = this;

	for(var i = 0; i < this.player.GetNumEntries(); i++)
	{
		if(!this.playList.entries[i])
		{
			var playlistitem = new ns_API.streaming.playlistItem({
		  			onPlayingCallback : function () { return function () {return this.player.GetPosition()}.apply(scope)},
		        episodeLength : 0,
		        clip : i + 1,
		        duration : 0       		
		  		});
		  	playlistitem.uid = this.playList.uid;
		  	playlistitem.sequence = 0;
				this.playList.addEntry(playlistitem);  		
		}			
	}
};

/**
 * @type ns_API.streaming.playlistItem
 */
ns_API.streaming.realPlayer.prototype.getSelectedItem = function()
{
	this.initPlayList();
	try
	{
		try
		{
			if(/stopped/i.test(this.playStates[this.player.GetPlayState()]) || this.doClipEndEvent)
				return (this.currentItem) ? this.currentItem : this.playList.entries[this.player.GetCurrentEntry()];
		} catch (e) {}
		return this.playList.entries[this.player.GetCurrentEntry()];
	} catch (e) { return null};
};

/**
 * @return index of current clip in playlist
 * @type Integer
 */
ns_API.streaming.realPlayer.prototype.getIndex = function()
{
	try
	{
		 return this.currentItem.clip-1;
	} catch (e) {return 0;}
};

/**
 * @type ns_API.streaming.playlist
 */
ns_API.streaming.realPlayer.prototype.getCurrentPlaylist = function () 
{
	return this.playList;
};

ns_API.streaming.realPlayer.prototype.onPostSeek = function ()
{
	if(this.player.GetPosition() == this.player.GetLength()) // fix for seeking to end of clip
		this.dispatchState("end",this.getSelectedItem());
	
	this.getSelectedItem().currentPosition = this.player.GetPosition();	
};

/**
 * @param {String} state
 */
ns_API.streaming.realPlayer.prototype.onPlayStateChange = function (state)
{
	var entry = this.getSelectedItem();
	
	if(this.playStates[state] && /stopped/i.test(this.playStates[state]))
	{
		var entry = this.getSelectedItem();
		this.doPlaylistEndEvent = true;
		if(entry) entry.sequence++;
	};	

	//this.doPlaylistStartEvent = (this.getSelectedItem().clip == 1) ? true : false;

	this._base.player.prototype.onPlayStateChange.apply(this,arguments);
	
	if(this.playStates[state] && /playing/i.test(this.playStates[state]))
		this.doPlaylistStartEvent = false; 	
};

ns_API.streaming.realPlayer.prototype.onPlayState_Playing = function ()
{
	var entry = this.getSelectedItem();

  if(!entry)
  	return;

	if(!entry.isOpened)
		this.onClipOpened();

	this.doClipEndEvent = false;
	if(this.currentItem != entry && this.currentItem && this.currentItem.playing)
	{
		this.doClipEndEvent = true;
		this.dispatchState("end",this.currentItem);		
	}
	else
	{
		this.doClipEvent = false;	
	}
	this.currentItem = entry;
    
	if(this.player.GetPosition() == this.player.GetLength() && !this.player.GetLiveState())
		return;

	this.playerVersion = (this.player.GetVersionInfo().replace(/\s/g,"") != "") ? this.player.GetVersionInfo() : this.playerVersion;	

	this.dispatchState("play",entry);
};

ns_API.streaming.realPlayer.prototype.onPlayState_Stopped = function ()
{
	var entry = this.getSelectedItem();
	if(!entry)
		return;
	
	this.doPlaylistEndEvent = true;	
	this.doPlaylistStartEvent = true;
  this.doClipEndEvent = true;    
	
	this.dispatchState("end", entry);
	entry.isOpened = false;	
	
	this.incrementPlaylist();
	this.doPlaylistEndEvent = false;
};

ns_API.streaming.realPlayer.prototype.onPlayState_Paused = function ()
{
	this.dispatchState("pause", this.getSelectedItem());
};


ns_API.streaming.realPlayer.prototype.onClipOpened = function ()
{
	if(this._base.DEBUG)
		this.player.SetMute(true);	

    var entry = this.getSelectedItem();
    if(!entry) return;
		entry.isOpened = true;
    this.doPlaylistStartEvent = (this.doClipEndEvent || this.doPlayListStartEvent || (!this.currentItem || (this.currentItem.clip != entry.clip && entry.clip == 1))) ? true : false;

    if(entry != this.currentItem)
  		entry.sequence++;  

		this.doClipEndEvent = false;
		entry.currentPosition = 0;
    entry.playing = false;	
    entry.events = 0;
    //entry.totalPlayed = 0;
    entry.bufferState = -1;
    entry.buffering = false;
};

ns_API.streaming.realPlayer.prototype.onClipClosed = function ()
{
   this.doClipEndEvent = true;
   this.currentItem.isOpened = false;
   this.dispatchState("end", this.currentItem);	
};


ns_API.streaming.realPlayer.prototype.onPlayState_Buffering = function ()
{
	var entry = this.getSelectedItem();
	this._base.player.prototype.onBuffering.call(this, true);
};


/**
 * @param {String} state
 */
ns_API.streaming.realPlayer.prototype.onBuffering = function (state)
{
	var entry = this.getSelectedItem();
	if(!entry)
		return;

	if(state != this.bufferState)
	{
		this.bufferState = state;
    this._base.player.prototype.onBuffering.call(this, (state == 0) ? true : false);
	}
};

/**
 * @type Long
 */
ns_API.streaming.realPlayer.prototype.getLabelValue_CA = function ()
{
	var playlist = this.getCurrentPlaylist();
	if(!playlist)
		return;
	
	var total = 0;
  for(var i = 0, value, entry; (entry = playlist.entries[i]); i++)
  {
  		value = entry["info"]["duration"];
  		total += (value == "undefined" || isNaN(parseInt(value)) ? 0 : parseInt(value)); 
  		if(value == 0)
  		{
  			value = this.getClipInfo("duration", i, null, this.getDurationFromString)
  			total += (value == "undefined" || isNaN(parseInt(value)) ? 0 : parseInt(value)); 
  		}
  }
  return total		
};

/**
 * @see ns_API.streaming.player#getLabelValue_LI
 */
ns_API.streaming.realPlayer.prototype.getLabelValue_LI = function () {return this.player.GetLiveState()};

/**
 * @see ns_API.streaming.player#getLabelValue_UB
 */
ns_API.streaming.realPlayer.prototype.getLabelValue_UB = function () 
{
	return this.player.GetBandwidthAverage(); // returns in bits not in Kb as supposed by the API documentation of WMP
};

/**
 * @see ns_API.streaming.player#getLabelValue_CS
 */
ns_API.streaming.realPlayer.prototype.getLabelValue_CS = function () 
{
	return String(this.player.GetClipWidth() + "x" + String(this.player.GetClipHeight()));
};

/**
 * @see ns_API.streaming.player#getLabelValue_BR
 */
ns_API.streaming.realPlayer.prototype.getLabelValue_BR = function () 
{
	/**
	 * this is unknown for realplayer
	 */ 
	return;
};

/**
 * @see ns_API.streaming.player#getLabelValue_ER
 */
ns_API.streaming.realPlayer.prototype.getLabelValue_ER = function () 
{
  return (this.player.GetLastErrorUserString() != "") ? this.player.GetLastErrorUserString() : null;
};

/**
 * @param {ns_API.streaming.playlistItem} _entry
 * @type Long
 */
ns_API.streaming.realPlayer.prototype.getEpisodeLength = function (_entry)
{
	var episode = _entry.getItemInfo("episode"), total = 0;	
	
	if(episode == "") return _entry.getItemInfo("duration");
	
	for(var i = 0, entry; (entry = this.playList.entries[0]); i++)
	{
		if(entry.getItemInfo("episode") == episode)
			total += entry.getItemInfo("duration");
	}

	return (total == 0) ? null : total;
};