
if (!Array.prototype.indexOf){
  Array.prototype.indexOf = function(elt) {
    var len = this.length;
    var from = Number(arguments[1]) || 0;
    from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    if (from < 0) from += len;
    for (; from < len; from++) {
      if (from in this && this[from] === elt)  return from;
    }
    return -1;
  };
}



var oc = {
  count: 1,

  initConsole: function() {
    var console = document.createElement('div');
    console.id = 'errorConsole';
    document.body.appendChild(console);
  //console.innerHTML = "<b>Error Console</b><br>";
  },

  writeToConsole: function(message) {
    message = oc.count + ':' + message;
    oc.count++;
    var newMessage = document.createElement('p');
    newMessage.innerHTML = message;
    var console = document.getElementById('errorConsole');
    console.appendChild(newMessage);
  }

};

oc.application = {
  name: undefined,
  description: undefined,
  serverHost: undefined,
  id: undefined,
  forumId: undefined,
  surface: 'canvas',

  serverUrl: function() {
    var url = 'http://' + oc.application.serverHost;
    return url;
  },

  canvasUrl: function() {
    var url = 'http://profile.myspace.com/Modules/Applications/Pages/Canvas.aspx?appId=' + oc.application.id;
    return url;
  },

  linkToCanvas: function (text) {
    var href = "<a href='" + oc.application.canvasUrl() + "'>"+text+"</a>";
    return href;
  },

  init: function(surface,name,description,hostname,id,forumId) {
    oc.application.surface = surface;
    oc.application.name = name;
    oc.application.description = description;
    oc.application.serverHost = hostname;
    oc.application.id = id;
    oc.application.forumId = forumId;
  }
  
};

oc.util = {
  generateId: function(el, prefix) {
    prefix = prefix || 'oc-gen';
    if (el && el.id) { // do not override existing ID
      return el.id;
    }
    var id = prefix + oc.count++;

    if (el) {
      el.id = id;
    }
    return id;
  },


  parseUriOptions: {
    strictMode: false,
    key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
    q:   {
      name:   "queryKey",
      parser: /(?:^|&)([^&=]*)=?([^&]*)/g
    },
    parser: {
      strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
      loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
    }
  },

  parseUri: function(str) {
    var	o   = oc.util.parseUriOptions;
    var m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str);
    var uri = {};
    var i  = 14;

    while (i--) uri[o.key[i]] = m[i] || "";

    uri[o.q.name] = {};
    uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
      if ($1) uri[o.q.name][$1] = $2;
    });

    return uri;
  },


  removeArrayMember: function(array,member) {
    var pos = array.indexOf(member);
    newArray = array.splice(pos,1);
    return newArray;
  },

  escape: function(str)
  {
    return encodeURIComponent(str);
  },

  unescape: function(str)
  {
    return decodeURIComponent(str);
  },

  isArray: function(obj)
  {
    return obj
    && typeof(obj)=='object'
    && obj.constructor
    && obj.constructor.toString().indexOf('Array')!=-1;
  },

  isArrayMember: function(array, member)
  {
    if(!array) return;
    for(var i=0; i<array.length; i++)
    {
      if(array[i]==member) return true;
    }
    return false;
  },

  arrayToQuery: function(assoc)
  {
    if(!assoc||typeof(assoc)!='object') return '';
    var pieces = [];
    for(var i in assoc)
    {
      if (i == 'indexOf') {
        
      } else if(typeof(assoc[i])=='object'&&assoc[i].length)  {
        pieces.push(oc.util.escape(i)+'='+oc.util.escape(assoc[i].join(',')));
      } else {
        pieces.push(oc.util.escape(i)+'='+oc.util.escape(assoc[i]));
      }
    }
    return pieces.join('&');
  },

  addPersonToQueryParams: function(person, key, params)
  {
    if(!person) return;
    var data = oc.os.getPersonData(person);
    for(var i in data) params[key+'_'+i] = data[i];
  },
  
  personToQueryString: function(person) {
    if(!person) return;
    var key = 'OC_viewer';
    var params = [];
    var data = person;
    for(var i in data) params[key+'_'+i] = data[i];
    var queryStr = oc.util.arrayToQuery(params);
    return queryStr;
  },

  prepUrlForQuery: function(url) {
    var lastChar = url[url.length-1];
    if(url.indexOf('?')==-1) url += '?';
    else if(lastChar!='?'&&lastChar!='&') url += '&';
    return url;
  }
};

oc.http =
{
  REQUEST_FAILED: 'REQUST_FAILED',
  _ATTEMPT_TIMEOUT: 2000,
  _ATTEMPT_LIMIT: 10,
  _GET: 1,
  _POST: 2,
  _BREAK_CACHE: true,
  _nextId: 1,
  _makeRequestParams: null,
  _calling: false,
  _trys: 0,
  _callback: null,
  _requests: {},

  Request: function(id, url, params, callback)
  {
    this.id = id;
    this.url = url;
    this.params = params;
    this.callback = callback;
    this.attempts = 0;
  },

  // public:

  setTimeout: function(timeout)
  {
    oc.http._ATTEMPT_TIMEOUT = timeout;
  },

  setAttemptLimit: function(attempt_limit)
  {
    oc.http._ATTEMPT_LIMIT = attempt_limit;
  },

  enableCacheBreaking: function()
  {
  	oc.http._BREAK_CACHE = true;
  },

  disableCacheBreaking: function()
  {
  	oc.http._BREAK_CACHE = false;
  },

  _baseUrl: function(path)
  {
    var url = oc.application.serverUrl();
    if(url.charAt(url.length-1)!='/') url += '/';
    if(path.charAt(0)=='/')
    {
      url += path.substring(1, path.length);
    } else {
      url += path;
    }
    return url;
  },

  get: function(url, callback)
  {
    var params = {};
    params[opensocial.ContentRequestParameters.AUTHORIZATION] = opensocial.ContentRequestParameters.AuthorizationType.SIGNED;
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
    oc.http._makeRequest(url, params, callback);
  },

  post: function(url, body, callback)  {
    var params = {};
    params[gadgets.io.RequestParameters.AUTHORIZATION] =  gadgets.io.AuthorizationType.SIGNED;
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
    params[gadgets.io.RequestParameters.POST_DATA] = body;
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
    oc.http._makeRequest(url, params, callback);
  },

  // private:

  _makeRequest: function(url, params, callback)
  {
    var request_id = oc.http._nextId++;
    var request =  new oc.http.Request(request_id, url, params, callback);
    request.url = oc.http._baseUrl(url);
    request.url =  oc.util.prepUrlForQuery(request.url)+'OC_app_id='+oc.application.id;
    request.url =  oc.util.prepUrlForQuery(request.url)+'OC_surface='+oc.application.surface;
    if(oc.http._BREAK_CACHE===true)	request.url = oc.util.prepUrlForQuery(request.url)+'r='+Math.random();
    oc.http._requests[request_id] = request;
    oc.http._attempt(request_id);
  },

  _recieve: function(request_id, rsp, error)
  {
    if(!rsp || !rsp.text) return;
    var request = oc.http._requests[request_id];
    if(!request) return;
    oc.http._requests[request_id] = null;
    request.callback(rsp.text);
  },

  _attempt: function(request_id)
  {
    var request = oc.http._requests[request_id];
    if(!request) return;
    var callback = function(rsp, error){ oc.http._recieve(request_id, rsp, error); };
    setTimeout('oc.http._check('+request_id+')', oc.http._ATTEMPT_TIMEOUT);
    request.attempts++;
    var url = request.url;
    var ret = gadgets.io.makeRequest(url, callback, request.params);
  },

  _check: function(request_id)
  {
    var request = oc.http._requests[request_id];
    if(request && request.attempts<oc.http._ATTEMPT_LIMIT)
    {
      oc.http._attempt(request_id);
    }
  }
};

oc.http_old =
{
  DISABLE_CACHE: true,

  _baseUrl: function(path)
  {
    var url = oc.application.serverUrl();
    if(url.charAt(url.length-1)!='/') url += '/';
    if(path.charAt(0)=='/')
    {
      url += path.substring(1, path.length);
    } else {
      url += path;
    }
    return url;
  },
  get: function(url, callback)
  {
    var params = {};
    params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
    oc.http._request(url,params,callback);
  },

  post: function(url, body, callback)
  {
    var params = {};
    params[gadgets.io.RequestParameters.AUTHORIZATION] =  gadgets.io.AuthorizationType.SIGNED;
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
    params[gadgets.io.RequestParameters.POST_DATA] = body;
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
    oc.http._request(url,params,callback);

  },

  _request: function(url,params,callback) {
    url = oc.http._baseUrl(url);
    url =  oc.util.prepUrlForQuery(url)+'OC_app_id='+oc.application.id;
    url =  oc.util.prepUrlForQuery(url)+'OC_surface='+oc.application.surface;
    if(oc.http.DISABLE_CACHE===true)	url = oc.util.prepUrlForQuery(url)+'r='+Math.random();
    var recieve = function(rsp,error) {
      callback(rsp.text);
    };
    gadgets.io.makeRequest(url, recieve, params);
  }

};

oc.os =  {
  _owner: null,
  _viewer: null,
  _viewerFriends: null,
  _viewerFriendsWithApp: null,
  _viewerFriendIds: [],
  _viewerFriendsWithAppIds: [],
  _people: {},
  _hasAppStatus: [],
  _lastError: undefined,


  idspec: {
    OWNER: 1,
    OWNER_FRIEND_IDS: 2,
    VIEWER: 3,
    VIEWER_FRIEND_IDS: 4,
    PERSON: [opensocial.Person.Field.ID,
    opensocial.Person.Field.NAME,
    opensocial.Person.Field.THUMBNAIL_URL,
    opensocial.Person.Field.PROFILE_URL,
    opensocial.Person.Field.HAS_APP,
    opensocial.Person.Field.STATUS,
    opensocial.Person.Field.MOOD]
  },

  people: {
    findById: function(ids,callback) {
      var people = [];
      var needed = [];
      var person = null;
      if (!oc.util.isArray(ids)) ids = [ids];
      for(var i=0; i<ids.length; i++){
        var p = oc.os.find_by_os_user_id(ids[i]);
        if (p) {
          people.push(p);
        } else {
          needed.push(ids[i]);
        }
      }
      if (needed.length >= 1) {
        oc.os._findByIds(needed, function(found) {
          found.each (function(p) {
            people.push(oc.os.find_by_os_user_id(p.getId()));
            callback(people);
          });
        });
      } else {
        callback(people);
      }
    }
  },

  find_by_os_user_id: function(id) {
    var person = oc.os.getPerson(id);
    if (person) {
      person = oc.os.getPersonData(person);
    }
    return person;
  },

  _findByIds: function(ids,callback) {
    var req = opensocial.newDataRequest();
    var params = {};
    req.add(req.newFetchPeopleRequest(ids, params), 'people');
    oc.os.sendDataRequest(req, function(dataResponse) {
      var people = oc.os.getData(dataResponse, 'people');
      if (people) {
        oc.os._addPeople(people);
      }
      callback(people);
    });
  },

  getPerson: function(id) {
    return oc.os._people[id];
  },

  _addPerson: function(person) {
    oc.os._people[person.getId()] = person;
  },

  _addPeople: function(people) {
    if(oc.util.isArray(people)) {
      for(var i=0; i<people.length; i++) oc.os._addPerson(people[i]);
    } else if(typeof(people.each)=='function') {
      people.each(function(person){
        oc.os._addPerson(person);
      });
    } else if(typeof(people.getId)=='function') {
      oc.os._addPerson(people);
    }
  },

  sendDataRequest: function (req,callback) {
    oc.os.DataRequest.send(req,callback);
  //        var responseCallback = function(dataResponse){
  //            callback(dataResponse);
  //        };
  //        req.send(responseCallback);
  },

  getData: function(rsp, key) {

    var item = rsp.get(key);
    if(!item) {
      return false;
    }
    if(item.hadError()) {
      oc.os._lastError = item.getErrorCode();
      return false;
    } else {
      return item.getData();
    }
  },

  getPersonData: function(person) {
    var data = {};
    data.id = person.getId();
    data.name = person.getDisplayName();
    data.first_name = data.name;
    data.last_name = '';
    data.thumbnail_url = person.getField(opensocial.Person.Field.THUMBNAIL_URL) || '';
    data.profile_url = person.getField(opensocial.Person.Field.PROFILE_URL) || '';
    data.has_app = oc.os._hasAppStatus[data.id];
    return data;
  },


  _checkData: function(dataRequest, key) {
    var item = dataRequest.get(key);
    if(item && item.hadError()) {
      oc.os._lastError = item.getErrorCode();
    }
    return item && item.hadError && (!item.hadError() || item.getErrorCode()==opensocial.ResponseItem.Error.UNAUTHORIZED);
  },

  getProfileUsers: function(callback) {
    var params = [];
    var os = opensocial.Container.get();
    var dataReqObj = os.newDataRequest();
    var viewerReq = os.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER);
    dataReqObj.add(viewerReq,'VIEWER');
    var ownerReq = os.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER);
    dataReqObj.add(ownerReq,'OWNER');
    dataReqObj.send(function(dataResponse) {
      if(oc.os._checkData(dataResponse, 'VIEWER')) {
        if(oc.os._viewer = oc.os.getData(dataResponse, 'VIEWER')) {
          oc.os._addPerson(oc.os._viewer);
          oc.util.addPersonToQueryParams(oc.os._viewer, 'OC_viewer', params);
        }
      }
      if(oc.os._checkData(dataResponse, 'OWNER')) {
        if(oc.os._owner = oc.os.getData(dataResponse, 'OWNER')) {
          oc.os._addPerson(oc.os._owner);
          oc.util.addPersonToQueryParams(oc.os._owner, 'OC_owner', params);
        }
      }
      var queryStr = oc.util.arrayToQuery(params);
      callback(queryStr);
    });
    
  },
  
  getViewer: function(callback) {
    var os = opensocial.Container.get();
    dataReqObj = os.newDataRequest();
    var viewerReq = os.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER);
    dataReqObj.add(viewerReq,'VIEWER');
    dataReqObj.send(function(dataResponse) {
      if(oc.os._checkData(dataResponse, 'VIEWER')) {
        if(oc.os._viewer = oc.os.getData(dataResponse, 'VIEWER')) {
          oc.os._addPerson(oc.os._viewer);
          callback(oc.os.getPersonData(oc.os._viewer));
        } else {
          callback('error');
        }
      } else {
        callback('error');
      }
    });
  },

  getOwner: function(callback) {
    os = opensocial.Container.get();
    dataReqObj = os.newDataRequest();
    var ownerReq = os.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER);
    dataReqObj.add(ownerReq,'OWNER');
    dataReqObj.send(function(dataResponse) {
      if(oc.os._checkData(dataResponse, 'OWNER')) {
        if(oc.os._owner = oc.os.getData(dataResponse, 'OWNER')) {
          oc.os._addPerson(oc.os._owner);
          callback(oc.os.getPersonData(oc.os._owner));
        } else {
          callback('error');
        }
      } else {
        callback('error');
      }
    });
  },
  
  navigateTo: function(surface,params){
    if (params == undefined) params = gadgets.views.getParams();
    if (surface == undefined) surface = 'canvas';
    var surfaces = gadgets.views.getSupportedViews();
    var surfaceRef = surfaces[surface];
    gadgets.views.requestNavigateTo(surfaceRef);
  }

};


oc.os.DataRequest =
{
  REQUEST_TIMED_OUT: 'REQUEST_TIMED_OUT',
  _request_timeout: 60000,
  _attempt_timeout: 2000,
  _attempt_limit: 10,
  _requests: {},
  _current: null,
  _sending: false,
  _nextId: 1,

  Request: function(id, req, callback)
  {
    this.id = id;
    this.req = req;
    this.callback = callback;
    this.attempts = 0;
  },


  // public:

  setRequestTimeout: function(timeout)
  {
    oc.os.DataRequest._request_timeout = timeout;
  },

  setAttemptTimeout: function(timeout)
  {
    oc.os.DataRequest._attempt_timeout = timeout;
  },

  setAttemptLimit: function(attempt_limit)
  {
    oc.os.DataRequest._attempt_limit = attempt_limit;
  },

  send: function(req, callback)
  {
    var request_id = oc.os.DataRequest._nextId++;
    var request = new oc.os.DataRequest.Request(request_id, req, callback);
    oc.os.DataRequest._requests[request_id] = request;
    oc.os.DataRequest._attempt(request_id);
    setTimeout('oc.os.DataRequest._timeout('+request_id+')', oc.os.DataRequest._request_timeout);
  },


  // private:

  _timeout: function(request_id)
  {
    var request = oc.os.DataRequest._requests[request_id];
    if(!request) return;
    oc.os.DataRequest._requests[request_id] = null;
    request.callback(oc.os.DataRequest.REQUEST_TIMED_OUT);
  },

  _recieve: function(request_id, dataResponse)
  {
    if(!dataResponse) return;
    var request = oc.os.DataRequest._requests[request_id];
    if(!request) return;
    oc.os.DataRequest._requests[request_id] = null;
    request.callback(dataResponse);
  },

  _attempt: function(request_id)
  {
    var request = oc.os.DataRequest._requests[request_id];
    if(!request) return;
    var callback = function(dataResponse){ 
      oc.os.DataRequest._recieve(request_id, dataResponse);
    };
    setTimeout('oc.os.DataRequest._check('+request_id+')', oc.os.DataRequest._attempt_timeout);
    request.attempts++;
    request.req.send(callback);
  },

  _check: function(request_id)
  {
    var request = oc.os.DataRequest._requests[request_id];
    if(request && request.attempts<oc.os.DataRequest._attempt_limit)
    {
      oc.os.DataRequest._attempt(request_id);
    }
  }
};



