/**
 * Part of JMF Library core
 * JMF - Base file for JMF Library
 * SVN: $Id: base.js 6163 2008-08-14 14:36:31Z mjezierski $ 
 */
 
/**
 * Abstract constructor for JMF library base class (namespace)
 * @constructor
 */
function JMF() {}
JMF.DEBUG = JMF.DEBUG === undefined?false:JMF.DEBUG;

JMF.profile = function(fname,namespace) {
	if(undefined === namespace) {
		namespace = window;
	} else {
		namespace = JMF.importClass(namespace);
	}
	
	var pfun = namespace[fname];
	
	namespace[fname] = function() {
		console.profile(fname);
		var res = pfun.apply(this,arguments);
		console.profileEnd();
	};
};

//global debugger
JMF._dbg = window.dbglx || {log:function(){},flog:function(){},error:function(){},warn:function(){}};

/** Render mode constants */
JMF.R_MODE_QUIRKS = 1;
JMF.R_MODE_STANDARD = 2;

JMF._locale = 'pl_ISO88592';

//Library dependency hash
JMF.libs = {};

/**
 * Registers lib in lib dependency hash
 * @member JMF
 */
JMF.registerLib = function(libName,svnId) {
   if(!JMF.DEBUG) {
   	return;
   }
   var fileName = '';
   if(svnId) {
   	 fileName = /([\w\_\.]+\.js)/i.exec(svnId);
   	 if(fileName) {
   	 	fileName = fileName[1];
   	 }
   	 else {
   	 	fileName = '';
   	 }
   }

	JMF.currentLib = libName + '['+fileName+']'; 
	JMF.libs[libName] = {name:libName,file:fileName};
	JMF._dbg.log('Registering lib: ' +JMF.libs[libName].name+', file: ' +JMF.libs[libName].file);
};

/**
 * Asserts if lib is registered in lib hash
 * Needs to be called at the beggining of every lib that is a part of JMF.Lib
 * @param {Mixed} libName Library name or array of required library names
 * @return {Boolean} True on success
 * @throws String with lack libs
 */
JMF.requireLib = function(libName) {
   if(!JMF.DEBUG) {
   	return true;
   }
   var assertArr = [];	if(libName instanceof Array) {
		for(var i=0;i<libName.length;i++) {
		   if(!JMF.libs[libName[i]]) {
		   	assertArr.push(libName[i]);
		   }	
		}
	} else {
      if(!JMF.libs[libName]) {
         assertArr.push(libName);
      }  
	}
	if(assertArr.length) {
		throw JMF.currentLib + ': Lib requirement assertion failed on: ' + assertArr.join(',');
	}
	return true;
};

JMF.domReady = false;

/**
 * This hash can be used to run alternate code
 * which depends on specific browser or render mode
 */
JMF.browser = (function() {
   var bdc = [
      //new RegExp not literal beecause of IE bug
      //RegExp literals are compiled once so actualy if you use it in array
      //the last one you used will be applied
      {rx:new RegExp("MSIE ([0-9\\.]{3})"),b:'IE'},       //IE
      {rx:new RegExp("Firefox\/([0-9\\.]{3})"),b:'FF'},   //FF
      {rx:new RegExp("Iceweasel\/([0-9\\.]{3})"),b:'FF'}, //FF/Debian
      {rx:new RegExp("Opera\/([0-9\\.]{3})"),b:'Opera'},   //Opera
      {rx:new RegExp("Version\/([0-9\\.]*)\\sSafari"),b:'Safari'}
   ];
   var bd;
   var browser = {};
   for(var i=0;i<bdc.length;i++) {
   	if((bd = bdc[i].rx.exec(navigator.userAgent))) {
         browser[bdc[i].b] = true;
         browser.version = parseFloat(bd[1]);
         browser.renderMode = document.compatMode == 'BackCompat'?JMF.R_MODE_QUIRKS:JMF.R_MODE_STANDARD;
         return browser;
   	}
   }
   return browser;
})();

/**
 * Function returns if current browser is on supported browsers list
 * @param {Array} Array of hashes [{b:'browser name',v:'minimal version'}]
 */
JMF.browser.isSupported = function(browserList) {
	for(var i=0;i<browserList.length;i++) {
		if(JMF.browser[browserList[i].b] && JMF.browser.version >= browserList[i].v) {
			return true;
		}
	}
	return false;
};


/**
 * @member JMF
 * Inherits class from superclasses
 * It does not inherit constructor.
 * Constructor should be called using call method superclass.constructorMethod.call(this,args)
 * @argument {Function} ... Inheriting class
 * @argument {Function} ... Inherited classes
 */
JMF.inherit = function(/*base class,...super classes...*/) {
   //use fast (5x faster) inheritance if there is only one class to inherit
   if(arguments.length == 2) {
   	var T = function(){};
   	T.prototype = arguments[1].prototype;
   	arguments[0].prototype = (new T());
   	return;
   }
   
   for(var argc=1;argc<arguments.length;argc++)  {
       var TmpClass = function(){};
       TmpClass.prototype = arguments[argc].prototype;
       var prototype = new TmpClass();
      /*jslint forin: false */
       for(var i in prototype) {
         arguments[0].prototype[i] = prototype[i];      
       }
      /*jslint forin: true */
   }
};

/**
 * Experimental - partially tested
 * Inherits class and when calling inheriting class method involves calling inherited class method if any
 * @param {Object} baseClass Inheriting class
 * @param {Object} superClass Inherited class
 */
JMF.bcInherit = function(baseClass,superClass) {
   function makeBCFunc(ffunc,sfunc) {
   	return function() {
   		ffunc.apply(this,arguments);
   		return sfunc.apply(this,arguments);
   	};
   }
   /*jslint forin: false */
   for(var i in superClass.prototype) {
   	if(baseClass.prototype[i] && (typeof baseClass.prototype[i] == 'function')) {
   		baseClass.prototype[i] = makeBCFunc(superClass.prototype[i],baseClass.prototype[i]);
   	} else {
   		baseClass.prototype[i] = superClass.prototype[i];
   	}
   }
   /*jslint forin: true */	
};

/**
 * Returns class reference from classpath string
 * @member JMF
 * @param {String} classPath Path to class (e.g. JMF.Data.OrderedList)
 * @return {Function} Class constructor
 */
JMF.importClass = function(classPath) {
   var ccPath = classPath.split('.');
   var cClass = window;
   for(var i=0;i<ccPath.length;i++) {
      cClass = cClass[ccPath[i]];
   }
   return cClass;	
};

/**
 * Generates uniqueId
 * @member JMF
 */
JMF.uId = function() {
	return 'uid'+(new Date()).getTime()+String.fromCharCode(Math.random()*26+64)+String.fromCharCode(Math.random()*26+64)+String(JMF.GUID++);
};

JMF.GUID = 0;