﻿/**
 * Copyright 2007 Fox Interactive Media
 * <DISCLAIMER HERE>
 * @fileoverview Interface for container and associated classes; everything needed to query/update MySpace API data via OpenSocial interface.
 * 
 * @author mnewbould [_at_] myspace [_dot_] com (Max Newbould)
 * @author crussell [_at_] myspace [_dot_] com (Chad Russell)
 */
 
 if (typeof(MyOpenSpace) == "undefined") MyOpenSpace = { Version: "0.7" };
 
 if (typeof(MyOpenSpace.ClientLibraries) == "undefined") MyOpenSpace.ClientLibraries = function () {};
 
 /**
  * Enum of client libraries supported for optional external include
  */
 MyOpenSpace.ClientLibraries.Scripts = {
    PROTOTYPE: 			"prototype",
    JQUERY: 			"jquery",
	MYSPACE_WIDGETS:	"myopensocial.widgets",
	SCRIPTACULOUS:		"scriptaculous",
    SILVERLIGHT:		"silverlight",
    MOOTOOLS: 			"mootools",
    AIR:	 			"adobeair"
 };
 
 /**
 * A stringbuilder implementation similar to .net - use in place of += for any strcat operations
 * @constructor
 * @name MyOpenSpace.StringBuilder
 */
 MyOpenSpace.StringBuilder = function(value) {
    this.strings_ = [];
    this.append(value);
 }
 /**
 * Appends a string
 * @member MyOpenSpace.StringBuilder
 */
 MyOpenSpace.StringBuilder.prototype.append = function (value) {
    if (value) this.strings_.push(value);
 }
 
 /**
 * Clears the stringbuilder
 * @member MyOpenSpace.StringBuilder
 */
 MyOpenSpace.StringBuilder.prototype.clear = function () {
    this.strings_.length = 0;
 }
 
 /**
 * Returns the string built
 * @member MyOpenSpace.StringBuilder
 */
 MyOpenSpace.StringBuilder.prototype.toString = function () {
    return this.strings_.join("");
 }
 
 
 /**
  * Dynamically include optional client libraries
  * @param {Object} script
  */
 MyOpenSpace.ClientLibraries.includeScript = function (scriptRef) {
 	var srcPath = "/OpenSocial/";
	var extSource = srcPath + "JSExtensions/";
	
	var root;
	try{
	    root = document.getElementsByTagName('head').item(0);
		if(!root){
			root = document.getElementsByTagName("body")[0];
		}
	}
	catch(ex){	}
	
	if(!root){
		throw "Malformed markup - no head or body element found";
	}
	
	var src = null;
	var libs = MyOpenSpace.ClientLibraries.Scripts;
	
	switch(scriptRef){
		case libs.MYSPACE_WIDGETS:
			src = srcPath + "MyOpenSpace001.Widgets.js";
			break;
		case libs.PROTOTYPE:
			src = extSource + "prototype/prototype.js";
			break;
		case libs.JQUERY:
			src = extSource + "jquery/jquery-1.2.3.min.js";
			break;
		case libs.SCRIPTACULOUS:
			src = extSource + "scriptaculous/scriptaculous-full-1.8.1.js";
			break;
		case libs.SILVERLIGHT:
			src = extSource + "silverlight/Silverlight.js";
			break;
		case libs.MOOTOOLS:
			src = extSource + "mootools/mootools-release-1.11.js";
			break;
		case libs.AIR:
			src = extSource + "air/AIRAliases.js";
			break;
	}
	
	if(!src){
		throw "Source script not found in supported list";
	}
	
    var scriptTag = document.createElement('script');
    scriptTag.setAttribute('language', 'javascript');
    scriptTag.setAttribute('type', 'text/javascript');
    scriptTag.setAttribute('src', src); 
    root.appendChild(scriptTag);
 }

 /**
 * An extension of opensocial.DataRequest, used to facilitate extended entity calls.
 * @class
 * @name MyOpenSpace.DataRequest
 */
MyOpenSpace.DataRequest = function() {};

function validateAppDataKeyName(keyName) {
    var validRE = /^([a-z0-9\-_\.])+$/i;
    return validRE.test(keyName);
} 
 // HS - Added tracing code
var MYOS_TRACE = false;
function myOsTrace(msg) {
	if (!MYOS_TRACE) {
		return;
	} else {
	    
		if (typeof console != "undefined" && typeof console.log == "function") {
			console.log(msg)
		} else {
	         var traceElm = document.getElementById('debugMessages');
             if (traceElm) {
                  traceElm.innerHTML += "<BR>" + msg;  
             }
	    }
	}
}


/**
 * @ignore
 */
Function.prototype.inherits = function(parentCtor) {
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  this.superClass_ = parentCtor.prototype;
  this.prototype = new tempCtor();
  this.prototype.constructor = this;
};

/** 
* @ignore 
* debugging utilities - reflect through an object's properties and trace values
*/
function reflect(obj, opt_dept, opt_currentDept){
	opt_dept = (opt_dept == undefined) ? 0 : opt_dept;
	opt_currentDept = (opt_currentDept == undefined) ? 0 : opt_currentDept;
	//trace(obj);
	if (typeof(obj) == "object"){
		for (var i in obj){
			var levelPrefix = '';
			for (var j = 0; j < opt_currentDept + 1; j++){
				levelPrefix += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
			}
			trace( levelPrefix + i + " -> " + obj[i] + "\n");
			if (typeof(obj[i]) == "object"){
				if (opt_dept > opt_currentDept){
						reflect(obj[i], opt_dept, opt_currentDept + 1);
				}
			}
		}
	}
}

var batchTrace = "";
/**
 * @ignore
 */
function tracePublicMembers(obj, propertyDepth) {
    propertyDepth = propertyDepth || 0;
    for (var prop in obj) {
        if (typeof(obj[prop]) == "function") return;
       
        if (typeof(obj[prop]) == "object")
        {
            traceIndent(propertyDepth);
            dumpToBatch("<b>" + prop + "</b><BR>", propertyDepth);
            tracePublicMembers(obj[prop], propertyDepth+1);
        }
        else
        {
            if (prop.substring(prop.length-3) != "___") {
                 traceIndent(propertyDepth);
                 dumpToBatch("<i>" + prop + "</i>: " + obj[prop] + "<BR>", propertyDepth);
                 }
        }
    }
    if (propertyDepth == 0) flushBatchTrace();
}
/**
 * @ignore
 */
function flushBatchTrace() {
    trace(batchTrace);
    batchTrace="";
}
/**
 * @ignore
 */
function dumpToBatch(msg, depth) {
    if (depth == 0) {
        batchTrace = msg + batchTrace;
    }
    else
    {
        batchTrace += msg;
    }
}
/**
 * @ignore
 */
function traceIndent(depth) {
    if (depth>0) {
        dumpToBatch("|", depth);
        for (var i = 0;i<depth;i++) dumpToBatch("----", depth);
        dumpToBatch(">", depth); 
    }
}
/**
 * @ignore
 */
function trace(msg, opt_no_break) {
    var traceElm = document.getElementById('debugMessages');
    if (traceElm) {
         opt_no_break = (opt_no_break) ? "" : "<BR>";
         traceElm.innerHTML += opt_no_break + msg;  
    }
}
//function reverseTrace(msg, opt_no_break) {
//    var traceElm = document.getElementById('debugMessages');
//    if (traceElm) {
//         opt_no_break = (opt_no_break) ? "" : "<BR>";
//         traceElm.innerHTML = msg + opt_no_break + traceElm.innerHTML;  
//    }
//}

/**
 * Internal implementation of a simple hash table.
 * @internal
 */
MyOpenSpace.Hash = function(){ 
    this._hash = {};
    this._num = 0;
};
MyOpenSpace.Hash.prototype = {
    _hash:null,
    _num:null,
    add:function(key, value){
        this._hash[key] = value;
        this._num++;
    },
    remove:function(key){
        var val = null;
        if("undefined" !== typeof(this._hash[key])){
            val = this._hash[key];
            delete this._hash[key];
            this._num--;
        }
        return val;
    },
    get:function(key){
        return _hash[key];
    },
    size:function(){
        return this._num;
    },
    has:function(key){
        if(!key) return false;
        return "undefined" !== typeof(this._hash[key]);
    }
};

/**
 * Borrowed from prototype
 * @ignore
 */
var Try = {
    /**
     * @function
     * @param Array of statements to evaluate for returnValues.
     * @ignore
     */
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}
