/*************************************************************************************************\
| AGI Media : flexible media presentation in web browsers
|--------------------------------------------------------------------------------------------------
|
| purpose
|-----------------------------------------------
|    > change div-boxes into app boxes and call each loading function
|    > define helper functions
|
| depends on
|-----------------------------------------------
|    > jquery.js
|
| version history
|-----------------------------------------------
|    1.1 // 04 may 2011
|       > Global
|            - merged former AGIMedia_CentralManagement.js and this AGIMedia.js
|            - deletion of obsolete AGIMedia_CentralManagement.js
|       > AGIMedia
|            - no more usage of obsolete AGIMedia.xml file
|            - xml-file deleted, functions deleted
|       > AGIMedia_Helper
|            - new function tryEnsureApp(path, loaderFuncName, appBox):
|                 > param path ends with a slash
|                 > calls app loading function (used by central management script)
|                 > returns:
|                      - true: if app loader script could be loaded and called
|                      - false: if app loader script could NOT be loaded OR called
|    1.0 // 02 may 2011
|       > AGIMedia
|            - implicit inclusion of app script files now also from within app folder
\*************************************************************************************************/

var AGIMedia_Lib_basePath = "/_layouts/AGI/AGIMedia/";
var AGIMedia_App_basePath = "/AGIMedia/";
var AGIMedia_basePath = AGIMedia_App_basePath;

var AGIMedia_includeScripts = [
	AGIMedia_basePath + "AGIMedia_GUILib.js"
];

///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
var AGIMedia_Helper = {

  expressionExists: function (varName) {
    try {
      eval("if (" + varName + ") {};");
    } catch (err) {
      return false;
    }
    return true;
  },

  //---------------------------------------------------------------------------------------------

  loadXMLFile_jQuery: function (path, readyFunction, errorFunction) {
    var xmlHttp = null;
    var ready = false;
    try { xmlHttp = new XMLHttpRequest(); }
    catch (e) {
      try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); }
      catch (e) {
        try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); }
        catch (e) { xmlHttp = null; }
      }
    }
    if (xmlHttp) {
      xmlHttp.open('GET', path, true);
      xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4 && readyFunction) {
          var xmlObject = xmlHttp.responseXML;
          var $root = $(xmlObject);
          if ($) // usage of jquery functionality
            while ($root == null || $root[0].tagName == undefined)
              $root = $root.children("*");
          readyFunction($root);
        }
      };

      xmlHttp.send(null);
    }

    if (!xmlHttp && errorFunction)
      errorFunction();
  },

  //---------------------------------------------------------------------------------------------

  convertJQueryTree_to_JSON: function ($tree) {
    var obj = {};
    var runTree = function ($node, node, level) {
      var attrs = $node[0].attributes;
      var __attrs = {};
      for (i = 0; i < attrs.length; i++)
        __attrs[attrs[i].name] = attrs[i].value;
      node["__attrs"] = __attrs;
      $node.children().each(function () {
        var nextNode = this;
        var $nextNode = $(nextNode);
        var tagName = nextNode.tagName;
        var hasSubs = $nextNode.children().length > 0;
        var hasSiblings = true; //$nextNode.siblings(tagName).length > 0;
        if (node[tagName] == undefined)
          node[tagName] = hasSiblings ? [] : {};
        var newNode = hasSubs ? {} : $nextNode.text(); ;
        if (hasSiblings)
          node[tagName].push(newNode);
        else
          node[tagName] = newNode;
        if (hasSubs)
          runTree($nextNode, newNode);
      });
    };

    runTree($tree, obj);
    return obj;
  },

  //---------------------------------------------------------------------------------------------

  loadXMLFileAsJSON: function (path, readyFunction, errorFunction) {
    var onReady = function ($xmlRoot) {
      readyFunction(AGIMedia_Helper.convertJQueryTree_to_JSON($xmlRoot));
    };
    AGIMedia_Helper.loadXMLFile_jQuery(path, onReady, errorFunction);
  },

  //---------------------------------------------------------------------------------------------

  getFileNameOfPath: function (path) {
    var slashPos = path.lastIndexOf("/");
    var fnam;
    if (slashPos > -1)
      fnam = path.substring(path.lastIndexOf("/") + 1);
    else
      fnam = path;
    var qmrkPos = fnam.indexOf("?");
    if (qmrkPos > -1)
      fnam = fnam.substring(0, qmrkPos);
    return fnam;
  },

  //---------------------------------------------------------------------------------------------

  // jquery required here! additionally load remote javascript file
  loadedScripts: {},
  includeJSFile: function (url) {
    $($("head > *")[0]).prepend("<script language=\"javascript\" src=\"" + url + "\"></script>");
  },
  ensureJSFile: function (url) {

    var currLowFileName = AGIMedia_Helper.getFileNameOfPath(url).toLowerCase();

    $foundScript = $("script").filter(function (idx) {
      var src;
      var lowFNam;
      if (src = $(this).attr('src'))
        lowFNam = AGIMedia_Helper.getFileNameOfPath(src).toLowerCase();
      else
        return false;

      if (AGIMedia_Helper.loadedScripts[lowFNam] == undefined) {
        AGIMedia_Helper.loadedScripts[lowFNam] = {
          name: lowFNam,
          url: src
        }
      }

      return currLowFileName == lowFNam;
    });

    if (AGIMedia_Helper.loadedScripts[currLowFileName] == undefined) {
      AGIMedia_Helper.loadedScripts[currLowFileName] = {
        name: currLowFileName,
        url: url
      }
      AGIMedia_Helper.includeJSFile(url);
    }
  },

  //---------------------------------------------------------------------------------------------

  trimString: function (str) {
    var newString = str.replace(/^\s*/, "");
    newString = newString.replace(/\s*$/, "");
    return newString;
  },

  //---------------------------------------------------------------------------------------------

  castNumber: function (obj) {
    return obj == null ? null :
			typeof (obj) == "number" ?
			appBox.params[0] :
			parseInt(obj) === NaN ?
				null :
				parseInt(obj);
  },

  //---------------------------------------------------------------------------------------------

  splitPseudoCallAndCssClasses: function (cssClassString) {
    //cssClassString = cssClassString.replace(/(\/)/g, "\\\/")
    //var pattern = /(AGIMedia::(\w+)\(\s*(\w+\s*(,\s*\w+[=]?\w*\s*)*)\))/;

    var pattern2 = /(AGIMedia::(\w+)\(([^\)]*)\))/;
    pattern2.exec(cssClassString);

    //pattern.exec(cssClassString);

    var callString = RegExp.$1;
    var callName = RegExp.$2;
    var paramListString = RegExp.$3;
    var paramList = [];

    var spltParams = paramListString.split(",");
    for (i = 0; i < spltParams.length; i++)
      paramList.push(this.trimString(spltParams[i]));

    var restString = cssClassString.replace(callString, "");
    restString = this.trimString(restString);
    return {
      cssClasses: restString,
      callString: callString,
      appID: callName,
      params: paramList
    };
  },

  //---------------------------------------------------------------------------------------------

  createIdForAppBox: function (appName) {
    var largeNumber1 = (new Date()).getTime();
    var largeNumber2 = Math.floor(Math.random() * 100000000000000000);
    var largeNumbers = largeNumber1 + "_" + largeNumber2;
    return "AGIMedia_" + appName + "_" + largeNumbers;
  },

  //---------------------------------------------------------------------------------------------

  isFunctionNameDefinedAndSecure: function (funcName, maxLen) {
    return (
			typeof (funcName) == "string" &&
			typeof (maxLen) == "number" &&
			funcName.length <= maxLen &&
			funcName.match(/\w+/) == funcName &&
			AGIMedia_Helper.expressionExists(funcName) &&
			typeof (eval(funcName)) == "function"
		);
  },

  //---------------------------------------------------------------------------------------------

  tryEnsureApp: function (path, loaderFuncName, appBox) {
    var appJSFileName = loaderFuncName + ".js";
    var pathApp = path + appJSFileName;
    this.includeJSFile(pathApp);
    var loaderFunc = this.getFunctionByNameIfDefinedAndSecure(loaderFuncName);
    if (typeof (loaderFunc) == "function") {
      loaderFunc(appBox);
      return true;
    }
    return false;
  },

  //---------------------------------------------------------------------------------------------

  getFunctionByNameIfDefinedAndSecure: function (funcName) {
    return AGIMedia_Helper.isFunctionNameDefinedAndSecure(funcName, 64) ? eval(funcName) : null;
  },

  //---------------------------------------------------------------------------------------------

  mergeObjects: function (minObj, majObj) {
    var runTree = function (pRes, pObj) {
      for (idxObj in pObj) {
        var valObj = pObj[idxObj];
        var typeof_valObj = typeof (valObj);
        var isObject = typeof_valObj == "object";
        var isArray = typeof_valObj == "array";
        var idxNotExists = pRes[idxObj] === undefined;
        if (isObject || isArray) {
          if (idxNotExists)
            pRes[idxObj] = isArray ? [] : {};
          runTree(pRes[idxObj], pObj[idxObj]);
        }
        else
          pRes[idxObj] = pObj[idxObj];
      }
    }

    var resObj = {};
    var pObj = minObj;
    runTree(resObj, pObj);

    pObj = majObj;
    runTree(resObj, pObj);

    return resObj;
  },

  //---------------------------------------------------------------------------------------------

  hasFlashPlugin: function (minVersion) {
    hasFlash = false;
    if (window.ActiveXObject) // is IE
    {
      try {
        var ob = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + minVersion);
        hasFlash = true;
      } catch (e) { }
    }
    else if ((navigator.plugins) && (navigator.plugins.length > 0)) { // not IE
      for (idx = 0; !hasFlash && idx < navigator.plugins.length; idx++) {
        var plugIsFlash = navigator.plugins[idx].name.toLowerCase().indexOf('flash') != -1;
        if (plugIsFlash) {
          if (navigator.plugins[idx].version) {
            var pointPos = navigator.plugins[idx].version.indexOf(".");
            var majorVersion = parseInt(navigator.plugins[idx].version.substring(0, pointPos));
            hasFlash = majorVersion >= minVersion;
          }
          else if (navigator.plugins[idx].description) {
            var descr = navigator.plugins[idx].description;
            var numStr = descr.substr(
							descr.indexOf("Flash") + 5
						);
            var pointPos = numStr.indexOf(".");
            var majorVersion = parseInt(numStr.substring(0, pointPos));
            hasFlash = majorVersion >= minVersion;
          }

        }

      }
    }
    return hasFlash;
  },

  //---------------------------------------------------------------------------------------------

  disableSelection: function (target) {
    if (typeof target.onselectstart != "undefined") //IE route
      target.onselectstart = function () { return false };
    else if (typeof target.style.MozUserSelect != "undefined") //Firefox route
      target.style.MozUserSelect = "none";
    else //All other route (ie: Opera)
      target.onmousedown = function () { return false };
    target.style.cursor = "default";
  },

  //---------------------------------------------------------------------------------------------

  enableSelection: function (target) {
    if (typeof target.onselectstart != "undefined") //IE route
      target.onselectstart = function () { return true }
    else if (typeof target.style.MozUserSelect != "undefined") //Firefox route
      target.style.MozUserSelect = "inherit"
    else //All other route (ie: Opera)
      target.onmousedown = function () { return true }
    target.style.cursor = "auto";
  }
};
//-------------------------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
var AGIMedia = (function() { var OBJ = {};

	// MEMBERS
	//---------------------------------------------------------------------------------------------

	OBJ = {
		documentReady: false,
		walkthroughStarted: false,
		hasError: false,
		errorMessage: "",
		app: {},
		currApps: [],
		
		//pointer to helper, guilib and more
		Helper: AGIMedia_Helper
	};
	
	// DATA CLASSES
	//---------------------------------------------------------------------------------------------
	OBJ.AppBoxData = function (ID, appID, techID, paramArr, domObject, loaderFunc) { return {
		ID: ID,
		appID: appID,
		techID: techID,
		params: paramArr,
		domObject: domObject,
		loaderFunc: loaderFunc
	};};
	
	// DOCUMENT-READY EVENT
	//---------------------------------------------------------------------------------------------
	//get and parse css-pseudo-calls
	$(document).ready(function()
	{
		//alert("DOCUMENT READY!");
		OBJ.documentReady = true;
		OBJ.ensureMainWalkthrough();
	});

	// METHODS
	//---------------------------------------------------------------------------------------------
	OBJ.setReadyForWalkthrough = function()
	{
		OBJ.readyForWalkthrough = true;
		OBJ.ensureMainWalkthrough();
	}

	//---------------------------------------------------------------------------------------------
	OBJ.ensureMainWalkthrough = function()
	{
		if(/*!OBJ.xmlLoaded || */!OBJ.documentReady || OBJ.hasError)
			return;
		//alert("ensureMainWalkthrough!");
		OBJ.walkthoughStarted = true;
		//get all css-class pseudo-calls
		$("[class^=AGIMedia::]").each(function() {
			var cssClass = $(this).attr("class");
			var cssSplitObj = AGIMedia_Helper.splitPseudoCallAndCssClasses(cssClass);
			$(this).attr("class", cssSplitObj.cssClasses);
			var domID = $(this).attr("id");
			if(domID == "") {
				domID = AGIMedia_Helper.createIdForAppBox(cssSplitObj.appID);
				$(this).attr("id", domID);
			}
			OBJ.currApps.push(OBJ.AppBoxData(domID, cssSplitObj.appID, null, cssSplitObj.params, this, null));
		});
		//handle all pseudo-calls
		OBJ.handleAppBoxes();
	};
	
	//---------------------------------------------------------------------------------------------
	OBJ.ensureApplicationTechnologyAndLoaderFunction = function(appID, techID, loaderFunction)
	{
		//alert("ensureApplicationTechnologyAndLoaderFunction");
		if(!this.app[appID])
			this.app[appID] = {};
		if(!this.app[appID][techID])
			this.app[appID][techID] = {};
		this.app[appID][techID]["LoaderFunction"] =
			(loaderFunction && typeof(loaderFunction) == "function") ? loaderFunction : null;
	};
	
	//---------------------------------------------------------------------------------------------
	// run through all put app boxes on the current html page and handle there creation
	OBJ.handleAppBoxes = function()
	{
		for(appBoxID in this.currApps) {
			var appBox = this.currApps[appBoxID];
			//=> ensure constructor function of application
			var loaderFuncName = "AGIMedia_App_" + appBox.appID;
			var deepPath = AGIMedia_basePath + loaderFuncName + "/";
			if(!AGIMedia_Helper.tryEnsureApp(deepPath, loaderFuncName, appBox))
				if(!AGIMedia_Helper.tryEnsureApp(AGIMedia_basePath, loaderFuncName, appBox))
					$(appBox.domObject).append(appBox.appID + " not implemented");
		}
	};
	
	
return OBJ;})();
//-------------------------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////////

(function() {
	for(idx in AGIMedia_includeScripts)
		AGIMedia_Helper.ensureJSFile(AGIMedia_includeScripts[idx]);
})();


