// Lyra.js
// 
// Copyright (c) 2009, makoto_kw (makoto.kw@gmail.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the makoto_kw nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY makoto_kw ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL makoto_kw BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

var Lyra = {
	version:'0.1.2',
	mediaElements: {},
	playStates: {
		acquiringLicense:1,
		buffering:2,
		closed:3,
		individualizing:4,
		opening:5,
		paused:6,
		playing:7,
		stopped:8
	},
	init: function(siverlightControlId) {
		var ret = false;
		try {
			this.siverlightControlId = siverlightControlId;
			this.host = document.getElementById(siverlightControlId);
			if (this.host) ret = true;
		} catch (ex) {}
		return ret;
	},
	isInitialized: function() {
		try {
			return (this.host != null && this.host.content != null && this.host.content.Lyra != null);
		} catch (e) {}
		return false;
	},
	createMediaElement: function(id) {
		try {
			// retry initialize
			if (!this.isInitialized && this.siverlightControlId) {
				this.init(this.siverlightControlId);
			}
			if (this.host) {
				// create Silverlight Lyra MediaElement
				var media = this.host.content.Lyra.CreateMediaElement(id);
				// create Javascript Lyra MediaElement
				return this.mediaElements[id] = new Lyra.MediaElement(media);
			}
		} catch (e) {/*alert(e);*/}
		return null;
	},
	findMediaElement: function(id) {
		return this.mediaElements[id];
	},
	apply:function(C,D,B){if(B){Lyra.apply(C,B)}if(C&&D&&typeof D=="object"){for(var A in D){C[A]=D[A]}}return C},
	applyIf:function(o,c){if(o&&c){for(var p in c){if(typeof o[p]=="undefined"){o[p]=c[p]}}}return o},
	override:function(origclass,overrides){if(overrides){var p=origclass.prototype;for(var method in overrides){p[method]=overrides[method]}}},
	extend:function(){var io=function(o){for(var m in o){this[m]=o[m]}};var oc=Object.prototype.constructor;return function(sb,sp,overrides){if(typeof sp=="object"){overrides=sp;sp=sb;sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this,arguments)}}var F=function(){},sbp,spp=sp.prototype;F.prototype=spp;sbp=sb.prototype=new F();sbp.constructor=sb;sb.superclass=spp;if(spp.constructor==oc){spp.constructor=sp}sb.override=function(o){Lyra.override(sb,o)};sbp.override=io;Lyra.override(sb,overrides);sb.extend=function(o){Lyra.extend(sb,o)};return sb}}()
};

// Lyra Ovserver pattern
Lyra.Observable=function(){};Lyra.Observable.prototype={fireEvent:function(){if(this.eventsSuspended!==true){var ce=this.events[arguments[0].toLowerCase()];if(typeof ce=="object"){return ce.fire.apply(ce,Array.prototype.slice.call(arguments,1));}}
return true;},filterOptRe:/^(?:scope|delay)$/,addListener:function(eventName,fn,scope,o){if(typeof eventName=="object"){o=eventName;for(var e in o){if(this.filterOptRe.test(e))continue;if(typeof o[e]=="function"){this.addListener(e,o[e],o.scope,o);}else{this.addListener(e,o[e].fn,o[e].scope,o[e]);}}
return;}o=(!o||typeof o=="boolean")?{}:o;eventName=eventName.toLowerCase();var ce=this.events[eventName]||true;if(typeof ce=="boolean"){ce=new Lyra.Event(this,eventName);this.events[eventName]=ce;}
ce.addListener(fn,scope,o);},removeListener:function(eventName,fn,scope){var ce=this.events[eventName.toLowerCase()];if(typeof ce=="object"){ce.removeListener(fn,scope);}},purgeListeners:function(){for(var evt in this.events){if(typeof this.events[evt]=="object"){this.events[evt].clearListeners();}}},addEvents:function(o){if(!this.events){this.events={};}
if(typeof o=='string'){for(var i=0,a=arguments,v;v=a[i];i++){if(!this.events[a[i]]){this.events[a[i]]=true;}}}else{Lyra.applyIf(this.events,o);}}};Lyra.Observable.prototype.on=Lyra.Observable.prototype.addListener;Lyra.Observable.prototype.un=Lyra.Observable.prototype.removeListener;(function(){var createDelayed=function(h,o,scope){return function(){var args=Array.prototype.slice.call(arguments,0);setTimeout(function(){h.apply(scope,args);},o.delay||10);};};Lyra.Event=function(obj,name){this.name=name;this.obj=obj;this.listeners=[];};Lyra.Event.prototype={addListener:function(fn,scope,options){scope=scope||this.obj;if(!this.isListening(fn,scope)){var l=this.createListener(fn,scope,options);if(!this.firing){this.listeners.push(l);}else{this.listeners=this.listeners.slice(0);this.listeners.push(l);}}},createListener:function(fn,scope,o){o=o||{};scope=scope||this.obj;var l={fn:fn,scope:scope,options:o};var h=fn;if(o.delay){h=createDelayed(h,o,scope);}
l.fireFn=h;return l;},findListener:function(fn,scope){scope=scope||this.obj;var ls=this.listeners;for(var i=0,len=ls.length;i<len;i++){var l=ls[i];if(l.fn==fn&&l.scope==scope){return i;}}
return-1;},isListening:function(fn,scope){return this.findListener(fn,scope)!=-1;},removeListener:function(fn,scope){var index;if((index=this.findListener(fn,scope))!=-1){if(!this.firing){this.listeners.splice(index,1);}else{this.listeners=this.listeners.slice(0);this.listeners.splice(index,1);}
return true;}return false;},clearListeners:function(){this.listeners=[];},fire:function(){var ls=this.listeners,scope,len=ls.length;if(len>0){this.firing=true;var args=Array.prototype.slice.call(arguments,0);for(var i=0;i<len;i++){var l=ls[i];if(l.fireFn.apply(l.scope||this.obj||window,arguments)===false){this.firing=false;return false;}}
this.firing=false;}return true;}};})();

Lyra.MediaElement = function(media){
	this.core = media;
	this.id = media.ID;
	Lyra.MediaElement.superclass.constructor.call(this);
	this.addEvents({
		"mediaopened":true,
		"mediafailed":true,
		"mediaended":true,
		"playstatechanged":true
	});
}
Lyra.extend(Lyra.MediaElement, Lyra.Observable, {
	setVolume: function(value) { this.core.Volume = value; },
	getVolume: function() { return this.core.Volume; },
	setPlayPosition: function(value) { this.core.Position = value; },
	getPlayPosition: function() { return this.core.Position; },
	getDuration: function() { return this.core.NaturalDuration; },
	getPlayState: function() { return this.core.CurrentState; },
	open: function(url) { return (url) ? this.core.Open(url) : false; },
	play: function() { this.core.Play(); },
	pause: function() { this.core.Pause(); },
	stop: function() { this.core.Stop(); }
});

// event handler from Silverlight application
function Lyra_onMediaOpened(sender){ var m = Lyra.findMediaElement(sender.ID); if (m) m.fireEvent("mediaopened"); }
function Lyra_onMediaFailed(sender){ var m = Lyra.findMediaElement(sender.ID); if (m) m.fireEvent("mediafailed"); }
function Lyra_onMediaEnded(sender){ var m = Lyra.findMediaElement(sender.ID); if (m) m.fireEvent("mediaended"); }
function Lyra_onMediaCurrentStateChanged(sender){ var id = sender.ID; setTimeout(function(){var m = Lyra.findMediaElement(id); if (m) m.fireEvent("playstatechanged");},0); }
