/**
 * @author Jorge Reyes jreyes A@T myspace [dot] com 
 */

/*
 * Extra Gadgest functionality
 * */
 
  var gadgets = gadgets || {};

  gadgets.config = function() {
  var components = {};

  return {
    /**
     * Registers a configurable component and its configuration parameters.
     *
     * @param {String} component The name of the component to register. Should
     *     be the same as the fully qualified name of the <Require> feature or
     *     the fully qualified javascript object reference (e.g. gadgets.io).
     * @param {Object} opt_validators Mapping of option name to validation
     *     functions that take the form function(data) {return isValid(data);}
     * @param {Function} opt_callback A function to be invoked when a
     *     configuration is registered. If passed, this function will be invoked
     *     immediately after a call to init has been made. Do not assume that
     *     dependent libraries have been configured until after init is
     *     complete. If you rely on this, it is better to defer calling
     *     dependent libraries until you can be sure that configuration is
     *     complete. Takes the form function(config), where config will be
     *     all registered config data for all components. This allows your
     *     component to read configuration from other components.
     * @throws {Error} If the component has already been registered.
     */
    register: function(component, opt_validators, opt_callback) {
      if (components[component]) {
        throw new Error('Component "' + component + '" is already registered.');
      }
      components[component] = {
        validators: opt_validators || {},
        callback: opt_callback
      };
    },

    /**
     * Retrieves configuration data on demand.
     *
     * @param {String} opt_component The component to fetch. If not provided
     *     all configuration will be returned.
     * @return {Object} The requested configuration.
     * @throws {Error} If the given component has not been registered
     */
    get: function(opt_component) {
      if (opt_component) {
        if (!components[opt_component]) {
          throw new Error('Component "' + opt_component + '" not registered.');
        }
        return configuration[opt_component] || {};
      }
      return configuration;
    },

    /**
     * Initializes the configuration.
     *
     * @param {Object} config The full set of configuration data.
     * @param {Boolean} opt_noValidation True if you want to skip validation.
     * @throws {Error} If there is a configuration error.
     */
    init: function(config, opt_noValidation) {
      configuration = config;
      for (var name in components) {
        var component = components[name],
            conf = config[name],
            validators = component.validators;
        if (!opt_noValidation) {
          for (var validator in validators) {
            if (!validators[validator](conf[validator])) {
              throw new Error('Invalid config value "' + conf[validator] +
                  '" for parameter "' + validator + '" in component "' +
                  name + '"');
            }
          }
        }
        if (component.callback) {
          component.callback(config);
        }
      }
    },

    // Standard validators go here.

    /**
     * Ensures that data is one of a fixed set of items.
     * @param {Array.<String>} list The list of valid values.
     * Also supports argument sytax: EnumValidator("Dog", "Cat", "Fish");
     */
    EnumValidator: function(list) {
      var listItems = [];
      if (arguments.length > 1) {
        for (var i = 0, arg; arg = arguments[i]; ++i) {
          listItems.push(arg);
        }
      } else {
        listItems = list;
      }
      return function(data) {
        for (var i = 0, test; test = listItems[i]; ++i) {
          if (data === listItems[i]) {
            return true;
          }
        }
      };
      return false;
    },

    /**
     * Tests the value against a regular expression.
     */
    RegExValidator: function(re) {
      return function(data) {
        return re.test(data);
      }
    },

    /**
     * Validates that a value was provided.
     */
    ExistsValidator: function(data) {
      return typeof data !== "undefined";
    },

    /**
     * Validates that a value is a non-empty string.
     */
    NonEmptyStringValidator: function(data) {
      return typeof data === "string" && data.length > 0
    },

    /**
     * Validates that the value is a boolean.
     */
    BooleanValidator: function(data) {
      return !!data;
    },

    /**
     * Similar to the ECMAScript4 virtual typing system, ensures that
     * whatever object was passed in is "like" the existing object.
     * Doesn't actually do type validation though, but instead relies
     * on other validators.
     *
     * example:
     *
     *  var validator = new gadgets.config.LikeValidator(
     *    "booleanField" : gadgets.config.BooleanValidator,
     *    "regexField" : new gadgets.config.RegExValidator(/foo.+/);
     *  );
     *
     * This can be used recursively as well to validate sub-objects.
     *
     * @param {Object} test The object to test against.
     */
    LikeValidator : function(test) {
      return function(data) {
        for (var member in test) {
          var t = test[member];
          if (!t(data[member])) {
            return false;
          }
        }
        return true;
      };
    }
  };
}();

	
	gadgets.util = function() {
  /**
   * Parses URL parameters into an object.
   * @return {Array.&lt;String&gt;} The parameters
   */
  function parseUrlParams() {
    // Get settings from url, 'hash' takes precedence over 'search' component
    // don't use document.location.hash due to browser differences.
    var query;
    var l = document.location.href;
    var queryIdx = l.indexOf("?");
    var hashIdx = l.indexOf("#");
    if (hashIdx === -1) {
      query = l.substr(queryIdx + 1);
    } else {
      // essentially replaces "#" with "&"
      query = [l.substr(queryIdx + 1, hashIdx - queryIdx - 1), "&",
               l.substr(hashIdx + 1)].join("");
    }
    return query.split("&");
  }

  var parameters = null;
  var features = {};
  var onLoadHandlers = [];

  return /** @scope gadgets.util */ {

    /**
     * Gets the URL parameters.
     *
     * @return {Object} Parameters passed into the query string
     * @member gadgets.util
     * @private Implementation detail.
     */
    getUrlParameters : function () {
      if (parameters !== null) {
        return parameters;
      }
      parameters = {};
      var pairs = parseUrlParams();
      var unesc = window.decodeURIComponent ? decodeURIComponent : unescape;
      for (var i = 0, j = pairs.length; i < j; ++i) {
        var pos = pairs[i].indexOf('=');
        if (pos === -1) {
          continue;
        }
        var argName = pairs[i].substring(0, pos);
        var value = pairs[i].substring(pos + 1);
        // difference to IG_Prefs, is that args doesn't replace spaces in
        // argname. Unclear on if it should do:
        // argname = argname.replace(/\+/g, " ");
        value = value.replace(/\+/g, " ");
        parameters[argName] = unesc(value);
      }
      return parameters;
    },

    /**
     * Creates a closure that is suitable for passing as a callback.
     * Any number of arguments
     * may be passed to the callback;
     * they will be received in the order they are passed in.
     *
     * @param {Object} scope The execution scope; may be null if there is no
     *     need to associate a specific instance of an object with this
     *     callback
     * @param {Function} callback The callback to invoke when this is run;
     *     any arguments passed in will be passed after your initial arguments
     * @param {Object} var_args Initial arguments to be passed to the callback
     *
     * @member gadgets.util
     * @private Implementation detail.
     */
    makeClosure : function (scope, callback, var_args) {
      // arguments isn't a real array, so we copy it into one.
      var tmpArgs = [];
      for (var i = 2, j = arguments.length; i < j; ++i) {
       tmpArgs.push(arguments[i]);
      }
      return function() {
        // append new arguments.
        for (var i = 0, j = arguments.length; i < j; ++i) {
          tmpArgs.push(arguments[i]);
        }
        callback.apply(scope, tmpArgs);
      };
    },

    /**
     * Utility function for generating an "enum" from an array.
     *
     * @param {Array.<String>} values The values to generate.
     * @return {Map&lt;String,String&gt;} An object with member fields to handle
     *   the enum.
     *
     * @private Implementation detail.
     */
    makeEnum : function (values) {
      var obj = {};
      for (var i = 0, v; v = values[i]; ++i) {
        obj[v] = v;
      }
      return obj;
    },

    /**
     * Gets the feature parameters.
     *
     * @param {String} feature The feature to get parameters for
     * @return {Object} The parameters for the given feature, or null
     *
     * @member gadgets.util
     */
    getFeatureParameters : function (feature) {
      return typeof features[feature] === "undefined"
          ? null : features[feature];
    },

    /**
     * Returns whether the current feature is supported.
     *
     * @param {String} feature The feature to test for
     * @return {Boolean} True if the feature is supported
     *
     * @member gadgets.util
     */
    hasFeature : function (feature) {
      return typeof features[feature] === "undefined";
    },

    /**
     * Registers an onload handler.
     * @param {Function} callback The handler to run
     *
     * @member gadgets.util
     */
    registerOnLoadHandler : function (callback) {
      onLoadHandlers.push(callback);
    },

    /**
     * Runs all functions registered via registerOnLoadHandler.
     * @private Only to be used by the container, not gadgets.
     */
    runOnLoadHandlers : function () {
      for (var i = 0, j = onLoadHandlers.length; i < j; ++i) {
        onLoadHandlers[i]();
      }
    },

    /**
     * @param {Object} featureData The features that are supported, and
     *    their parameters.
     * @private Only to be used by the container, not gadgets.
     */
    init : function (featureData) {
      features = featureData;
    }
  };
}();

gadgets.views = function() {

  /**
   * Reference to the current view object.
   */
  var currentView = null;

  /**
   * Map of all supported views for this container.
   */
  var supportedViews = {};

  /**
   * Map of parameters passed to the current request.
   */
  var params = {};

  /**
   * Initializes views. Assumes that the current view is the "view"
   * url parameter (or default if "view" isn't supported), and that
   * all view parameters are in the form view-<name>
   * TODO: Use unified configuration when it becomes available.
   *
   */
  function init(config) {
    var supported = config["views"];

    var x = 0;
    for (var s in supported) if (supported.hasOwnProperty(s)) {
      var obj = supported[s];
      supportedViews[s] = new gadgets.views.View(obj.name_, obj.isOnlyVisible_);
      //HACK BELOW
      supportedViews[x] = supportedViews[s];x++;//HACK for back compat to 0.6 container
      //REMOVE ABOVE LINE AT SOME POINT
      var aliases = obj.aliases || [];
      for (var i = 0, alias; alias = aliases[i]; ++i) {
        supportedViews[alias] = new gadgets.views.View(obj.name_, obj.isOnlyVisible_);
      }
   } 

    var urlParams = gadgets.util.getUrlParameters();
    // View parameters are passed as a single parameter.
    if (urlParams["view-params"]) {
      var tmpParams = gadgets.json.parse(
          decodeURIComponent(urlParams["view-params"]));
      if (tmpParams) {
        params = tmpParams;
      }
    }
    currentView = supportedViews[urlParams.views] || supportedViews["default"];
  }

  var requiredConfig = {
    "default": new gadgets.config.LikeValidator({
      "isOnlyVisible_" : gadgets.config.BooleanValidator
    })
  };

  gadgets.config.register("views", requiredConfig, init);

  return {
    requestNavigateTo : function(view, opt_params) {
      gadgets.rpc.call(
          null, "requestNavigateTo", null, view.getName(), opt_params);
    },

    getCurrentView : function() {
      return currentView;
    },

    getSupportedViews : function() {
      return supportedViews;
    },

    getParams : function() {
      return params;
    }
  };
}();

gadgets.views.View = function(name, opt_isOnlyVisible) {
  this.name_ = name;
  this.isOnlyVisible_ = !!opt_isOnlyVisible;
};

gadgets.views.View.prototype.getName = function() {
  return this.name_;
};

gadgets.views.View.prototype.isOnlyVisibleGadget = function() {
  return this.isOnlyVisible_;
};

gadgets.views.ViewType = gadgets.util.makeEnum([
  "FULL_PAGE", "DASHBOARD", "POPUP"
]);

/**
 * @static
 * @class Provides operations for getting information about and modifying the
 *     window the gadget is placed in.
 * @name gadgets.window
 */
gadgets.window = gadgets.window || {};

// we wrap these in an anonymous function to avoid storing private data
// as members of gadgets.window.
(function() {

  var oldHeight;

  /**
   * Detects the inner dimensions of a frame.
   * See: http://www.quirksmode.org/viewport/compatibility.html for more
   * information.
   * @returns {Object} An object with width and height properties.
   * @member gadgets.window
   */
  gadgets.window.getViewportDimensions = function() {
    var x,y;
    if (self.innerHeight) {
      // all except Explorer
      x = self.innerWidth;
      y = self.innerHeight;
    } else if (document.documentElement &&
               document.documentElement.clientHeight) {
      // Explorer 6 Strict Mode
      x = document.documentElement.clientWidth;
      y = document.documentElement.clientHeight;
    } else if (document.body) {
      // other Explorers
      x = document.body.clientWidth;
      y = document.body.clientHeight;
    } else {
      x = 0;
      y = 0;
    }
    return {width: x, height: y};
  };
  
  /**
 * Adjusts the gadget height
 * @param {Number} opt_height An optional preferred height in pixels. If not
 *     specified, will attempt to fit the gadget to its content.
 * @member gadgets.window
 */
gadgets.window.adjustHeight = function(opt_height) {
    var newHeight = parseInt(opt_height, 10);
    var percentage = false;
    if(isNaN(newHeight)){
        var vh = gadgets.window.getViewportDimensions().height;
        var body = document.body;
        var docEl = document.documentElement;
        if (document.compatMode == 'CSS1Compat' && docEl.scrollHeight){
            newHeight = docEl.scrollHeight != vh ? docEl.scrollHeight : docEl.offsetHeight;
        }
        else{
            var sh = docEl.scrollHeight;
            var oh = docEl.offsetHeight;

            if(docEl.clientHeight != oh){
                sh = body.scrollHeight;
                oh = body.offsetHeight;
            }

            if(sh > vh){
                newHeight = sh > oh ? sh : oh;
            }
            else{
                newHeight = sh < oh ? sh : oh;
            }
            
            if(newHeight === vh &&
                    window.navigator &&
                    window.navigator.userAgent &&
                    window.navigator.userAgent.toLowerCase().indexOf("safari") >= 0){ //for safari, quite ugly...
                var newDiv = document.createElement("div");
                newDiv.innerHTML = document.body.innerHTML;
                newDiv.style.visibility = "hidden";
                newDiv.id = "_temp_____div_for_____adjustHeight";
                document.body.appendChild(newDiv);
                newHeight = document.getElementById("_temp_____div_for_____adjustHeight").offsetHeight + 15;
                newDiv.innerHTML = "";
                document.body.removeChild(newDiv);
            }
        }
    }
    else if(0 === newHeight){
        newHeight = parseFloat(opt_height);
        if(!isNaN(newHeight) && (newHeight <= 1 || newHeight > 0)) percentage = true;
    }

    if (newHeight != oldHeight || percentage) {
        oldHeight = newHeight;
        var p = opensocial.Container.get().params_;
        _IFPC.call(
            p.panelId,
            "resizeWidget",
            [p.panelId , newHeight],
            p.remoteRelay,
            null,
            p.localRelay,
            null); 
    }
};
}());   








if (typeof(MyOpenSpace) === "undefined") MyOpenSpace = { };

MyOpenSpace.Util = {};

MyOpenSpace.Util.parseIdPrefix = function(id){
    var results = ('' + id).match(/^(?:myspace\.com:)?(\d+)$/);
    if (results === null || results.length === 0) {
        return null;
    }
    return results[1];
};

MyOpenSpace.Activity = function(params) {
    this.fields_ = params || {};
};


MyOpenSpace.Activity.Field = {
	TITLE_ID : 'titleId',
	TITLE : 'title',
	TEMPLATE_PARAMS : 'templateParams',
	URL : 'url',
	MEDIA_ITEMS : 'mediaItems',
	BODY_ID : 'bodyId',
	BODY : 'body',
	EXTERNAL_ID : 'externalId',
	STREAM_TITLE : 'streamTitle',
	STREAM_URL : 'streamUrl',
	STREAM_SOURCE_URL : 'streamSourceUrl',
	STREAM_FAVICON_URL : 'streamFaviconUrl',
	PRIORITY : 'priority',
	ID : 'id',
	USER_ID : 'userId',
	APP_ID : 'appId',
	POSTED_TIME : 'postedTime'
};

MyOpenSpace.Activity.prototype.getId = function() {
	return this.getField(MyOpenSpace.Activity.Field.ID);
};

MyOpenSpace.Activity.prototype.getField = function(key) {
	return this.fields_[key];
};

MyOpenSpace.Activity.prototype.setField = function(key, data) {
	return this.fields_[key] = data;
};


MyOpenSpace.CreateActivityPriority = {
  HIGH : 'HIGH',
  LOW : 'LOW'
};


MyOpenSpace.MediaItem = function(mimeType, url, opt_params) {
  this.fields_ = opt_params || {};
  this.fields_[MyOpenSpace.MediaItem.Field.MIME_TYPE] = mimeType;
  this.fields_[MyOpenSpace.MediaItem.Field.URL] = url;
};


MyOpenSpace.MediaItem.Type = {
  IMAGE : 'image',
  VIDEO : 'video',
  AUDIO : 'audio'
}

MyOpenSpace.MediaItem.Field = {
  TYPE : 'type',
  MIME_TYPE : 'mimeType',
  URL : 'url'
};

MyOpenSpace.MediaItem.prototype.getField = function(key) {
  return this.fields_[key];
};


MyOpenSpace.MediaItem.prototype.setField = function(key, data) {
  return this.fields_[key] = data;
};



MyOpenSpace.Permission = function() { };

/**
* The available permission types
* @class
* @name MyOpenSpace.Permission.Field
* @static
* @internal
*/
MyOpenSpace.Permission.Field = {
    DISPLAY_ON_PROFILE: "DisplayOnProfile",
    DISPLAY_ON_HOME: "DisplayOnHome",
    SEND_UPDATES_TO_FRIENDS: "SendUpdatesToFriends",
    SHOW_UPDATES_FROM_FRIENDS: "ShowUpdatesFromFriends",
    ACCESS_TO_PRIVATE_VIDEOS_PHOTOS: "AccessToPrivateVideosPhotos",
    ACCESS_TO_PUBLIC_VIDEOS_PHOTOS: "AccessToPublicVideosPhotos",
	ACCESS_TO_IDENTITY_INFORMATION: "AccessToIdentityInformation",
	ADD_PHOTOS_TO_ALBUMS: "AddPhotosAlbums",
	UPDATE_MOOD_STATUS: "UpdateMoodStatus",
	UPDATE_PROFILE: "UpdateProfile",
	CONTACT_INFO: "ViewContactInfo",
	FULL_PROFILE_INFO: "ViewFullProfileInfo",
	
	BASIC_COMMUNICATIONS: "BasicCommunications",
	ACCESS_TO_FRIEND_LIST: "AccessToFriendList",
	ACCESS_TO_BASIC_INFO: "BasicInfo"
};


/**
* The available permission settings that can be checked
* @class
* @name MyOpenSpace.Permission
* @static
*/
MyOpenSpace.Permission = {
	

    VIEWER_DISPLAY_ON_PROFILE: {
        permission: MyOpenSpace.Permission.Field.DISPLAY_ON_PROFILE,
		permissionIndicator : "DP"
    },

    VIEWER_DISPLAY_ON_HOME: {
        permission: MyOpenSpace.Permission.Field.DISPLAY_ON_HOME,
		permissionIndicator : "DH"
    },

    VIEWER_SEND_UPDATES_TO_FRIENDS: {
        permission: MyOpenSpace.Permission.Field.SEND_UPDATES_TO_FRIENDS,
		permissionIndicator : "UT"
    },

    VIEWER_SHOW_UPDATES_FROM_FRIENDS: {
        permission: MyOpenSpace.Permission.Field.SHOW_UPDATES_FROM_FRIENDS,
		permissionIndicator : "UF"
    },

    VIEWER_ACCESS_TO_PRIVATE_VIDEOS_PHOTOS: {
        permission: MyOpenSpace.Permission.Field.ACCESS_TO_PRIVATE_VIDEOS_PHOTOS,
		permissionIndicator : "PR"
    },

    VIEWER_ACCESS_TO_PUBLIC_VIDEOS_PHOTOS: {
        permission: MyOpenSpace.Permission.Field.ACCESS_TO_PUBLIC_VIDEOS_PHOTOS,
		permissionIndicator : "PB"
    },
	VIEWER_ACCESS_TO_IDENTITY_INFORMATION:{
        permission: MyOpenSpace.Permission.Field.ACCESS_TO_IDENTITY_INFORMATION,
		permissionIndicator : "AI"
	},
	VIEWER_ADD_PHOTOS_TO_ALBUMS:{
        permission: MyOpenSpace.Permission.Field.ADD_PHOTOS_TO_ALBUMS,
		permissionIndicator : "PA"		
	},
	VIEWER_UPDATE_MOOD_STATUS:{
        permission: MyOpenSpace.Permission.Field.UPDATE_MOOD_STATUS,
		permissionIndicator : "UM"		
	},
	VIEWER_UPDATE_PROFILE:{
        permission: MyOpenSpace.Permission.Field.UPDATE_PROFILE,
		permissionIndicator : "UP"		
	},
	VIEWER_CONTACT_INFO:{
        permission: MyOpenSpace.Permission.Field.CONTACT_INFO,
		permissionIndicator : "VC"
	},
	VIEWER_FULL_PROFILE_INFO:{
        permission: MyOpenSpace.Permission.Field.FULL_PROFILE_INFO,
		permissionIndicator : "VF"		
	},
	VIEWER_ACCESS_TO_BASIC_INFO:{
        permission: MyOpenSpace.Permission.Field.ACCESS_TO_BASIC_INFO,
		permissionIndicator : "BI"		
	},
	VIEWER_ACCESS_TO_FRIEND_LIST:{
        permission: MyOpenSpace.Permission.Field.ACCESS_TO_FRIEND_LIST,
		permissionIndicator : "FL"		
	},
	VIEWER_BASIC_COMMUNICATIONS:{
        permission: MyOpenSpace.Permission.Field.BASIC_COMMUNICATIONS,
		permissionIndicator : "BC"
	}
};

MyOpenSpace.View = {};

MyOpenSpace.View.Field = {
    CANVAS:"canvas",
    PROFILE_LEFT:"profile.left",
    PROFILE_RIGHT:"profile.right",
    PROFILE:"profile",
    HOME:"home",
    DEFAULT:"canvas"
};

MyOpenSpace.Message = function(body, opt_params) {
  this.fields_ = opt_params || {};
  this.fields_[MyOpenSpace.Message.Field.BODY] = body;
};

MyOpenSpace.Message.Field = {

  TYPE : 'type',
  TITLE : 'title',
  BODY : 'body',
  TITLE_ID : 'titleId',
  BODY_ID : 'bodyId'
};


MyOpenSpace.Message.prototype.getField = function(key) {
  return this.fields_[key];
};

MyOpenSpace.Message.prototype.setField = function(key, data) {
  return this.fields_[key] = data;
};


MyOpenSpace.PostTo = {};

MyOpenSpace.PostTo.Targets = {
    PROFILE:"PROFILE",
    SEND_MESSAGE:"SEND_MESSAGE",
    COMMENTS:"COMMENTS",
    BULLETINS:"BULLETINS",
    BLOG:"BLOG",
    SHARE_APP:"SHARE_APP",
	ACTIVITY:"ACTIVITY"
};

MyOpenSpace.PostTo.Result = {
	ERROR: -1,
	CANCELLED: 0,
	SUCCESS: 1
};

MyOpenSpace.MySpaceContainer = function() {
    
    gadgets.util.getUrlParameters().views = gadgets.util.getUrlParameters().opensocial_surface;//HACK ALERT
    var config = {};
    var supported_views = {};
    supported_views["default"] = new gadgets.views.View(MyOpenSpace.View.Field.DEFAULT, true);
    supported_views[MyOpenSpace.View.Field.CANVAS] = new gadgets.views.View(MyOpenSpace.View.Field.CANVAS, true);
    
    config["views"] = supported_views;
    gadgets.config.init(config);

    this.osMode_ = gadgets.views.getCurrentView();
    var uriFragment = window.location.hash;
    if (uriFragment && uriFragment.length >= 0) {
        uriFragment = uriFragment.substring(1,uriFragment.length);
        if(uriFragment.indexOf("&") >= 0){
            uriFragment = uriFragment.substring(0, uriFragment.indexOf("&"));
        }
    }
	
    this.params_ = {};
    
    var urlParams = gadgets.util.getUrlParameters();
	
	if (urlParams &&  urlParams.opensocial_token){
		this.params_["osToken"] = urlParams.opensocial_token;
	}
	
	if (urlParams &&  urlParams.opensocial_owner_id){
		this.params_["ownerid"] = urlParams.opensocial_owner_id;
	}
	
	if (urlParams.opensocial_viewer_id){
		this.params_["viewerId"] = urlParams.opensocial_viewer_id;
	}
	
	
	if (urlParams &&  urlParams.appid){
		this.params_["appid"] = urlParams.appid;
	}
	
    if (urlParams && urlParams.ptoString) {
        this.params_["supportedPostToTargets"] = urlParams.ptoString.split(",");
    }
	else{
		this.params_["supportedPostToTargets"] = ["COMMENTS","BLOG","BULLETINS","PROFILE","SEND_MESSAGE","SHARE_APP"];
	}
	
	if (urlParams.userBlockedApp){
		this.params_["appBlocked"] = true;
	}
	else{
		this.params_["appBlocked"] = false;
	}
	
	if (urlParams.userLoggedOut){
		this.params_["loggedOut"] = true;
	}
	else{
		this.params_["loggedOut"] = false;
	}

    if (urlParams.installState) {
        this.params_["installState"] = "" + urlParams.installState;
    }
	else{
		this.params_["installState"] = "1"
	}
	
	if (urlParams.perm) {
	    perm = gadgets.json.parse('{"permissions":' + urlParams.perm + "}");
        this.params_["viewerPerm"] = perm.permissions;
    }
	else{
		this.params_["viewerPerm"] = [];
	}
	
	MyOpenSpace.MDPContainerRSAMultipleRecipients = true;
	MyOpenSpace.MDPContainerUseOpenCanvas = true;
	MyOpenSpace.EnableClientCache = false;
	
	if (urlParams && urlParams.mc) {
        var mc = urlParams.mc.split(",");
        for (var i = 0; i < mc.length; i++) {
            switch (mc[i]) {
                case "UOC":
                    MyOpenSpace.MDPContainerUseOpenCanvas = false;
                    break;
                case "RSAMR":
                    MyOpenSpace.MDPContainerRSAMultipleRecipients = false;
                    break;
                case "ECC":
                    MyOpenSpace.EnableClientCache = true;
                    break;
            }
        }
    }
	
	this.params_["remoteRelay"] = "http://profile.myspace.com/Modules/Applications/Pages/ifpc_relay.aspx";
}
MyOpenSpace.MySpaceContainer.container_ = new MyOpenSpace.MySpaceContainer();

MyOpenSpace.MySpaceContainer.get = function(){
	return MyOpenSpace.MySpaceContainer.container_;
}

MyOpenSpace.MySpaceContainer.prototype.getQueryString = function(){
	var qryString = window.location.search.substring(1);
	var perms = this.params_["viewerPerm"];
	var permission = "";
	for (var i = 0; i < perms.length; i++){
		if (permission[i] !== ''){
			if (permission !== '') permission += "%2C";
			permission += "%22" + perms[i] + "%22"
		}
	}
	permission = "[" + permission + "]";
	qryString = qryString.replace(/&perm=(.*?)&/, "&perm=" + permission + "&");
	
	if ("" + this.params_["installState"] === "1"){
		return qryString.replace(/&installState=(.*?)&/, "&installState=1&")
	}
	else{
		return qryString.replace(/&installState=(.*?)&/, "&installState=0&")
	}
}


MyOpenSpace.MySpaceContainer.prototype.newMediaItem = function(mimeType, url,
    opt_params) {
  return new MyOpenSpace.MediaItem(mimeType, url, opt_params);
};

MyOpenSpace.MySpaceContainer.prototype.newActivity = function(opt_params) {
  return new MyOpenSpace.Activity(opt_params);
};


var _IFPC = window["_IFPC"];

MyOpenSpace.MySpaceContainer.prototype.registerParam = function(key, value) {
    this.params_[key] = value;
};

MyOpenSpace.MySpaceContainer.prototype.getParam = function(key) {
    return this.params_[key];
};


MyOpenSpace.MySpaceContainer.prototype.newMessage = function(body, opt_params) {
  return new MyOpenSpace.Message(body, opt_params);
};

MyOpenSpace.MySpaceContainer.prototype.requestCreateActivity = function(activity, priority, opt_callback){
	var container = MyOpenSpace.MySpaceContainer.get();
    if(!container.hasPermission(MyOpenSpace.Permission.VIEWER_SEND_UPDATES_TO_FRIENDS)){
        if(opt_callback){
            var ri = {
				"errorCode" : "UNAUTHORIZED", 
				"errorMessage" : "You do not have permission to send an activities. Send updates to friends permission is required."
			};
            opt_callback(ri);
        }
        return;
    }
    if (!activity || !activity.getField(MyOpenSpace.Activity.Field.TITLE_ID)) {
        if(opt_callback){
            var ri = {
				"errorCode" : "BAD_REQUEST",
				"errorMessage": "You must supply an MyOpenSpace.Activity object with a TITLE_ID."
			};
            opt_callback(ri);
        }
        return;
    }
   
	
    var convertActivityToMessage = function(activity){
        var body, title, title_id, body_id, type = MyOpenSpace.PostTo.Targets.ACTIVITY;
        var container = MyOpenSpace.MySpaceContainer.get();
        
        // parse media items, save them to the message body
        if (activity.getField(MyOpenSpace.Activity.Field.MEDIA_ITEMS) && activity.getField(MyOpenSpace.Activity.Field.MEDIA_ITEMS).length > 0) {
            var mediaItemsOld = activity.getField(MyOpenSpace.Activity.Field.MEDIA_ITEMS);
            var mediaItemsNew = "{";

            for (var i = 0; i < mediaItemsOld.length; i++) {
                if (0 !== i) {
                    mediaItemsNew += ",";
                }
                mediaItemsNew += "\"" + mediaItemsOld[i].getField(MyOpenSpace.MediaItem.Field.URL) + "\"";
            }
            mediaItemsNew += "}";

            body = escape(mediaItemsNew);
        }
        
        // parse template params, save them to the title
        if (activity.getField(MyOpenSpace.Activity.Field.TEMPLATE_PARAMS)) {
            title = escape(gadgets.json.stringify(activity.getField(MyOpenSpace.Activity.Field.TEMPLATE_PARAMS)));
        }
        
        // parse title id, save them to the title id
        title_id = escape(activity.getField(MyOpenSpace.Activity.Field.TITLE_ID));
        
        // parse priority, save them to the body id
        body_id = activity.getField(MyOpenSpace.Activity.Field.PRIORITY);
        
        var params = {};
        params[MyOpenSpace.Message.Field.TITLE] = title;
        params[MyOpenSpace.Message.Field.TITLE_ID] = title_id;
        params[MyOpenSpace.Message.Field.TYPE] = type;
        params[MyOpenSpace.Message.Field.BODY_ID] = priority;
		
        return container.newMessage(body, params);
    };
    
    if(priority) activity.setField(MyOpenSpace.Activity.Field.PRIORITY, priority);
    var message = convertActivityToMessage(activity);
    
    container.postTo(message, opt_callback);
};

MyOpenSpace.MySpaceContainer.prototype.adjustHeight = function(opt_height) {
    var newHeight = parseInt(opt_height, 10);
    var percentage = false;
    if(isNaN(newHeight)){
        var vh = gadgets.window.getViewportDimensions().height;
        var body = document.body;
        var docEl = document.documentElement;
        if (document.compatMode == 'CSS1Compat' && docEl.scrollHeight){
            newHeight = docEl.scrollHeight != vh ? docEl.scrollHeight : docEl.offsetHeight;
        }
        else{
            var sh = docEl.scrollHeight;
            var oh = docEl.offsetHeight;

            if(docEl.clientHeight != oh){
                sh = body.scrollHeight;
                oh = body.offsetHeight;
            }

            if(sh > vh){
                newHeight = sh > oh ? sh : oh;
            }
            else{
                newHeight = sh < oh ? sh : oh;
            }
            
            if(newHeight === vh &&
                    window.navigator &&
                    window.navigator.userAgent &&
                    window.navigator.userAgent.toLowerCase().indexOf("safari") >= 0){ //for safari, quite ugly...
                var newDiv = document.createElement("div");
                newDiv.innerHTML = document.body.innerHTML;
                newDiv.style.visibility = "hidden";
                newDiv.id = "_temp_____div_for_____adjustHeight";
                document.body.appendChild(newDiv);
                newHeight = document.getElementById("_temp_____div_for_____adjustHeight").offsetHeight + 15;
                newDiv.innerHTML = "";
                document.body.removeChild(newDiv);
            }
        }
    }
    else if(0 === newHeight){
        newHeight = parseFloat(opt_height);
        if(!isNaN(newHeight) && (newHeight <= 1 || newHeight > 0)) percentage = true;
    }

	var oldHeight = gadgets.window.getViewportDimensions().height;
    if (newHeight != oldHeight || percentage) {
        var p = this.params_;
        _IFPC.call(
            p.panelId,
            "resizeWidget",
            [p.panelId , newHeight],
            p.remoteRelay,
            null,
            p.localRelay,
            null); 
    }
};

MyOpenSpace.MySpaceContainer.prototype.requestNavigateTo = function(view, opt_params) {

    if (view) {
        if (0 === view.indexOf("profile.")) view = "profile";
        var p = this.params_;
        _IFPC.call(
            p.panelId,
            "requestNavigateTo",
            [p.appid, p.ownerid, view.toLowerCase(), opt_params],
            p.remoteRelay,
            null,
            p.localRelay,
            null);
    }
}


MyOpenSpace.MySpaceContainer.prototype.postTo = function(message,opt_callback, recipientId, recipientName, recipientThumbnail, recipientProfileUrl ){
    if (MyOpenSpace.View.Field.CANVAS !== gadgets.views.getCurrentView().getName()) {
		return {
			"errorCode": "BAD_REQUEST",
			"errorMessage": "PostTo does not support this view, only the canvas view is supported."
		}; 
	}
    var target_is_supported = false;
    var supported = this.params_.supportedPostToTargets;
    
    var messageSubject = "";
	var messageBody;
	var messageType;
	
    if(null !== message && "undefined" !== typeof(message)){
        messageSubject = message.getField(MyOpenSpace.Message.Field.TITLE);
        messageBody = message.getField(MyOpenSpace.Message.Field.BODY);
        messageType = message.getField(MyOpenSpace.Message.Field.TYPE);
    }
    else{
		if (opt_callback)
        opt_callback( {
			"errorCode": "BAD_REQUEST",
			"errorMessage": "You must supply a valid Message object."
		}); 
		return;
    }
	
	if (messageType === MyOpenSpace.PostTo.Targets.SHARE_APP){
		this.requestShareApp(recipientId, message, opt_callback);
		return;
	}
    
    for(var i = 0; i < supported.length; i++){
        if(supported[i] === messageType){
            target_is_supported = true;
            break;
        }
    }
    
    if (!target_is_supported) {
		if (opt_callback)
		opt_callback( {
			"errorCode": "BAD_REQUEST",
			"errorMessage": "That PostTo target is not supported."
		});
		return;
	}

	var token = this.params_.osToken;
	if (typeof(token) === 'undefined'){
		if (opt_callback)
		opt_callback( {
			"errorCode": "BAD_REQUEST",
			"errorMessage": "Open social token not set."
		});
		return;
	}
	var priority = null;
	var titleId = null;
	if(messageType === MyOpenSpace.PostTo.Targets.ACTIVITY){
		titleId = message.getField(MyOpenSpace.Message.Field.TITLE_ID);
		priority = message.getField(MyOpenSpace.Message.Field.BODY_ID);
		recipientId = this.params_.viewerId; 
	}
	
	var panelId = this.params_.panelId;
    _IFPC.call(
            panelId,
            "postTo",
            [token, messageType, 
			messageSubject, messageBody, recipientId, recipientThumbnail,
			recipientName, recipientProfileUrl, titleId, priority, this.params_.appid],
            this.params_.remoteRelay,
            opt_callback,
            this.params_.localRelay,
            null);
};


MyOpenSpace.MySpaceContainer.prototype.requestShareApp = function(recipients, reason, opt_callback) {
	 if (MyOpenSpace.View.Field.CANVAS !== gadgets.views.getCurrentView().getName()) {
		if (opt_callback) {
			return {
				"errorCode": "BAD_REQUEST",
				"errorMessage": "requestShareApp does not support this view, only the canvas view is supported."
			};
		}
		return;
	}
	
    if (typeof(reason) === 'undefined' || typeof(reason.getField) === 'undefined') {
		if (opt_callback) {
			opt_callback( {
				"errorCode": "BAD_REQUEST",
				"errorMessage": "Invalid opensocial.Message object for parameter 'reason'."
			});
		}
		return;
	}
	
	var supported = this.params_.supportedPostToTargets;
	for(var i = 0; i < supported.length; i++){
        if(supported[i] === MyOpenSpace.PostTo.Targets.SHARE_APP){
            target_is_supported = true;
            break;
        }
    }

    if (!target_is_supported){
		if (opt_callback) {
			opt_callback( {
				"errorCode": "BAD_REQUEST",
				"errorMessage": "requestShareApp is not supported or temporarily disabled."
			});
		}
		return;
	}
	
	if (typeof(recipients) === 'undefined' || recipients === null){
		opt_callback( {
			"errorCode": "BAD_REQUEST",
			"errorMessage": "'recipients' parameter is required."
		});
		return;
	}
			
	if (recipients.constructor !== Array){
		recipients = [recipients];
	}
	else if(false === MyOpenSpace.MDPContainerRSAMultipleRecipients && recipients.length > 1){
	    if (opt_callback) {
			opt_callback( {
				"errorCode": "NOT_IMPLEMENTED",
				"errorMessage": "requestShareApp does not currently support multiple recipients."
			});
		}
		return;
	}
	else if(recipients.length > 10){
	    if (opt_callback) {
			opt_callback( {
				"errorCode": "BAD_REQUEST",
				"errorMessage": "You can only share the app with a maximum of 10 friends."
			});
		}
		return;
	}

    var results, ids = [];
    for(var i = 0; i < recipients.length; i++){
	    results = MyOpenSpace.Util.parseIdPrefix(recipients[i]);
        if (results === null) {
		    if(opt_callback){
				opt_callback( {
					"errorCode": "BAD_REQUEST",
					"errorMessage": "Invalid id, IDs must be strings or array of strings, in the format '6221' or 'myspace.com:6221'"
				});
		    }
		    return;
        }
        
        ids.push(results);
    }
        
    var subject = reason.getField(MyOpenSpace.Message.Field.TITLE);
    var body = reason.getField(MyOpenSpace.Message.Field.BODY);
    
	
    _IFPC.call(this.params_.panelId,
        "postTo",
        [this.params_.osToken, MyOpenSpace.PostTo.Targets.SHARE_APP,
        subject, body, ids.join(","), null,
        null, null, null, null, this.params_.appid],
        this.params_.remoteRelay,
        opt_callback,
        this.params_.localRelay,
        null);
};

/**
* Returns true if the current gadget has access to the specified
* permission. If the gadget calls opensocial.requestPermission and permissions
* are granted then this function must return true on all subsequent calls.
*
* @internal
* @private
*/
MyOpenSpace.MySpaceContainer.prototype.hasPermission = function(permission) {
	var params = this.params_;
	var appBlocked = params.appBlocked;
	var loggedOut = params.loggedOut;

	if ((appBlocked || loggedOut)){
		return false;
	}
	
	var checkPermsissions = function(permission){
		var userPermissions = params.viewerPerm;
	
	    for (var i in userPermissions) {
	        if (userPermissions[i] === permission.permissionIndicator) {
	            return true;
	        }
	    }
	
	    return false;
	}

	var installState = params.installState;

	
	if (
		permission.permissionIndicator === "BI" || permission.permissionIndicator === "BC" ||
		permission.permissionIndicator === "FL"
	){
		if (installState === "0") {
			return checkPermsissions(permission);
		}
		else{
			return true;
		}
	}
	else if (installState === "0"){
		return false;
	}

	return checkPermsissions(permission);
    
}


MyOpenSpace.MySpaceContainer.prototype.requestPermission = function(permission, reason, opt_callback){
	var params = this.params_;
	var supportedPermissions = [
		MyOpenSpace.Permission.VIEWER_DISPLAY_ON_PROFILE,
		MyOpenSpace.Permission.VIEWER_DISPLAY_ON_HOME,
		MyOpenSpace.Permission.VIEWER_SEND_UPDATES_TO_FRIENDS,
		MyOpenSpace.Permission.VIEWER_ACCESS_TO_PRIVATE_VIDEOS_PHOTOS,
		MyOpenSpace.Permission.VIEWER_ACCESS_TO_PUBLIC_VIDEOS_PHOTOS,
		MyOpenSpace.Permission.VIEWER_SHOW_UPDATES_FROM_FRIENDS,
		MyOpenSpace.Permission.VIEWER_ACCESS_TO_IDENTITY_INFORMATION,
		MyOpenSpace.Permission.VIEWER_ADD_PHOTOS_TO_ALBUMS,
		MyOpenSpace.Permission.VIEWER_UPDATE_MOOD_STATUS,
		MyOpenSpace.Permission.VIEWER_UPDATE_PROFILE,
		MyOpenSpace.Permission.VIEWER_CONTACT_INFO,
		MyOpenSpace.Permission.VIEWER_FULL_PROFILE_INFO
	];
	
	if (MyOpenSpace.View.Field.CANVAS !== gadgets.views.getCurrentView().getName()) {
		return {
			"errorCode": "NOT_IMPLEMENTED",
			"errorMessage": "requestPermission does not support this view, only the canvas view is supported."
		}; 
	}
	
    var validatedPermissions = new Array();
	//Check that is a valid permission object
	if (permission && typeof(permission.permission) !== 'undefined'){
		//Check if the permission is supported	
		for (var supported  in supportedPermissions){
			if (supportedPermissions[supported].permission === permission.permission){
				//check if the user doesn't have the requested permission.
				if (!this.hasPermission(permission)){
	                validatedPermissions.push(permission.permission);									
				}
				break;
			}
		}
	}


    
    var userGrantedPermissions_sync = function (permissionState){
		var currentContainer = MyOpenSpace.MySpaceContainer.get();
        if(permissionState){
			var currentPermissions = params.viewerPerm;
			var permissionsGranted = [];
			var allPermissionsGranted = true;
            for(var key in permissionState){
				var permObj = null;
				var granted = permissionState[key];

				if (key == "installed"){
					currentContainer.registerParam("installState", 1);
					continue;
				}
				allPermissionsGranted &= granted;
				for (var permIdex in supportedPermissions){
					if (supportedPermissions[permIdex].permission.toLowerCase() === key.toLowerCase()){
						permObj = supportedPermissions[permIdex];
						break;
					}
				}
				if (permObj !== null){
					if (granted) {
						permissionsGranted.push(permObj);
					}
					var permissionExist = false;
					var permissionIndex = 0;
					//Add permission to viewerPerm if is not there
					for (var permIndex in currentPermissions){
						if (currentPermissions[permIdex] === permObj.permissionIndicator){
							permissionExist = true;
							permissionIndex = permIndex;
							break;
						}
					}
					if (!permissionExist && granted) {
						currentPermissions.push(permObj.permissionIndicator);
						currentContainer.registerParam("viewerPerm", currentPermissions);
					}
					else if (permissionExist && !granted){
						currentPermissions.splice(permissionIndex, 1);
						currentContainer.registerParam("viewerPerm", currentPermissions);
					}
				}
            }
			if (opt_callback) {
				if (allPermissionsGranted && permissionsGranted.length > 0) {	
					opt_callback({
						"permissions": permissionsGranted
					});
				}
				else if (!allPermissionsGranted && permissionsGranted.length > 0){
					opt_callback({
						"permissions": permissionsGranted,
						"errorCode": "UNAUTHORIZED",
						"errorMessage": "No all the permissions were granted."
					});
				}
				else {
					opt_callback({
						"errorCode" : "UNAUTHORIZED",
						"errorMessage": "No new permissions were granted."
					});
				}
				return;
			}
        }
        else{
            if(opt_callback) opt_callback({
				"errroCode" : "UNAUTHORIZED",
				"errorMessage": "No new permissions were granted."
			});
			return;
        }
    };
    
	if (validatedPermissions.length === 0) {
		if(opt_callback) opt_callback({
			"errroCode" : "BAD_REQUEST",
			"errorMessage": "No valid permissions were requested."
		});
		return;
	}
	_IFPC.call(params.panelId, 
		"requestPermission", 
		[params.appid, validatedPermissions, reason], 
		params.remoteRelay, 
		userGrantedPermissions_sync, 
			params.localRelay, 
			null);
    
};


