(function($) {

  var interval = null;
  var checklist = [];

  $.elementReady = function(id, fn) {
    checklist.push({
      id: id,
      fn: fn
    });
    if (!interval) {
      interval = setInterval(check, $.elementReady.interval_ms);
    }
    return this;
  };

  // Plugin settings
  $.elementReady.interval_ms = 23; // polling interval in ms

  // Private function
  function check() {
    var docReady = $.isReady; // check doc ready first; thus ensure that check is made at least once _after_ doc is ready
    for (var i = checklist.length - 1; 0 <= i; --i) {
      var el = document.getElementById(checklist[i].id);
      if (el) {
        var fn = checklist[i].fn; // first remove from checklist, then call function
        checklist[i] = checklist[checklist.length - 1];
        checklist.pop();
        fn.apply(el, [$]);
      }
    }
    if (docReady) {
      clearInterval(interval);
      interval = null;
    }
  };

})(jQuery);

var $j = jQuery.noConflict();

oc.canvas = {
  _path: null,
  _require: null,
  _navParams: null,
  _nextId: 1,
  _requests: {},
  TIMED_OUT: false,
  
  newUser: false,
  viewParams: undefined,
  contentDiv: undefined,
  containerDiv: undefined,
  
  getViewer: function() {
    return oc.os._viewer;
  },

  getViewerFriends: function() {
    return oc.os._viewerFriends;
  },

  getViewerFriendIds: function() {
    return oc.os._viewerFriendIds;
  },

  _reset: function() {
    oc.os._viewer = null;
    oc.os._owner = null;
    oc.os._viewerFriends = null;
    oc.os._viewerFriendIds = [];
    oc.os._viewerFriendsWithApp = null;
    oc.os._people = {};
  },

  _request: function(id, options) {
    this.httpMethod = 'get';
    this.fetchIds = [];
    this.path = options['path'];
    this.id = id;

    if (options['params']) {
      this.extraParams = options['params'];
    }
    if (options['update']) {
      this.updateDiv = options['update'];
    }
    if (options['callback']) {
      this.callback = options['callback'];
    }
    if (options['fetch_ids']) {
      this.fetchIds = options['fetch_ids'];
    }
    if (options['http_method']) {
      this.httpMethod = options['http_method'];
    }
  },

  loadingContent: function() {
    var loading = '<h1 style="margin: 20px 10px; font-size: 200%;">Loading Be A Tycoon....</h1>';
    loading = loading + '<h4>If Be A Tycoon does not load within 30 seconds, ' + oc.application.linkToCanvas("click here") + ' to reload the page.</h4>';
    return loading;
  },

  init: function(containerDiv,contentDiv,path) {
    oc.canvas.contentDiv = contentDiv;
    oc.canvas.containerDiv = containerDiv;
    $j('#loading').html(oc.canvas.loadingContent());
    $j('#loading').css('display','');
    $j('#' + oc.canvas.contentDiv).css('display','none');
    //location.href = '#anchorTop';

    oc.canvas.viewParams = gadgets.views.getParams();

    oc.canvas._fetch({
      http_method: 'post',
      path: path,
      update: oc.canvas.contentDiv
    });
  },

  get: function(path,options) {
    options['path'] = path;
    options['http_method'] = 'get';
    oc.canvas._fetch(options);
  },

  post: function(path,options) {
    options['path'] = path;
    options['http_method'] = 'post';
    oc.canvas._fetch(options);
  },

  _fetch: function(options) {
    oc.canvas.TIME_OUT = false;
    gadgets.window.adjustHeight(3000);
    oc.canvas.loading();
    var request_id = oc.canvas._nextId++;
    var request =  new oc.canvas._request(request_id, options);
    oc.canvas._requests[request_id] = request;
    oc.canvas._require = [oc.os.idspec.VIEWER_FRIEND_IDS, oc.os.idspec.VIEWER];
    if(!oc.canvas.data._fetch(request_id, oc.canvas._require, oc.canvas._dataCB)) {
      oc.canvas._dataCB(request_id);
    }
  },

  logRequest: function(error) {
    var path = '/main/log';
    var queryParams = oc.canvas.setQueryParams();
    var queryStr = oc.util.arrayToQuery(queryParams);
    queryStr = queryStr + '&' + 'log_request=1';
    queryStr = queryStr + '&' + 'log_error=' + error;
    oc.http.post(path,queryStr, function(body) {

      });
  },
  
  setQueryParams: function() {
    var queryParams = [];

    if(oc.canvas._navParams) queryParams = oc.canvas._navParams;

    for(var i in oc.canvas.viewParams) {
      queryParams[i] = oc.canvas.viewParams[i];
    }
    // add viewer
    if(oc.os._viewer) {
      oc.canvas._addPersonToQueryParams(oc.os._viewer, 'OC_viewer', queryParams);
    }

    if(oc.os._viewerFriendIds.length > 0) {
      oc.canvas._addFriendIdsToQueryParams(oc.os._viewerFriendIds, 'OC_viewer_friends', queryParams);
    }

    if (oc.os._viewerFriendsWithApp != null) {
      oc.os._viewerFriendsWithAppIds = [];
      for(var i=0; i<oc.os._viewerFriendsWithApp.length; i++){
        oc.os._viewerFriendsWithAppIds.push(oc.os._viewerFriendsWithApp[i].getId());
      }

      if(oc.os._viewerFriendsWithAppIds.length > 0) {
        oc.canvas._addFriendIdsToQueryParams(oc.os._viewerFriendsWithAppIds, 'OC_viewer_friends_with_app', queryParams);
      }
    }

    return queryParams;
  },

  _dataCB: function(request_id) {
    
    var request = oc.canvas._requests[request_id];
    var require = oc.canvas._require;
    var queryParams = oc.canvas.setQueryParams();
    var queryStr = oc.util.arrayToQuery(queryParams);
    
    if (request.extraParams) {
      queryStr = queryStr + '&' + request.extraParams;
    }

    if (oc.canvas.newUser) {
      queryStr = queryStr + '&' + 'OC_new_user=1';
    }
    
    if (request.httpMethod == 'post') {
      oc.http.post(request.path,queryStr, function(body) {
        oc.canvas._fetchCB(request_id,body);
      });
    } else {
      var query = oc.util.prepUrlForQuery(request.path)+queryStr;
      oc.http.get(query, function(body) {
        oc.canvas._fetchCB(request_id,body);
      });
    }
  },

  _fetchCB: function(request_id,body)  {
    var request = oc.canvas._requests[request_id];
    if (request.callback) {
      request.callback(body);
    } else if (request.updateDiv) {
      $j('#' + request.updateDiv).html(body);
      oc.canvas.render();
      $j('#loading').css('display','none');
      $j('#' + oc.canvas.contentDiv).css('display','');
      if (!oc.canvas.newUser) {
        location.href = '#anchorTop';
      }
    }
    oc.canvas.finishedLoading();
  },

  _addFriendsToQueryString: function(friends, key, queryStr){
    var pieces = [];
    friends.each(function(person){
      if(!person) return;
      var data = oc.os.getPersonData(person);
      for(var i in data) {
        var pid = person.getId();
        var str = 'friends['+person.getId()+']['+i+']';
        pieces.push(str + '=' + encodeURIComponent(data[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];
  },
  _addFriendIdsToQueryParams: function(friendIds, key, params)
  {
    params[key] = friendIds;

  },

  loading: function(){
    $j('#oc_loader').show();
    $j('#' + oc.canvas.containerDiv).css('cursor','wait');
  },

  finishedLoading: function() {
    $j('#oc_loader').hide();
    $j('#' + oc.canvas.containerDiv).css('cursor','default');
  },

  render: function(id) {
    if (!id) {
      id = oc.canvas.contentDiv;
    }
    $j.elementReady(id, function(){
      var classNames = ['os_user_background','os_user_name','os_user_thumbnail_url','os_user_id','os_user_profile_url'];
      for(var i=0; i<classNames.length; i++){
        $j('.' + classNames[i]).each (function(index) {
          var element = $j(this);
          if(element.attr('os_user_id')) {
            var value = undefined;
            var person = oc.os.getPerson(element.attr('os_user_id'));
            if (!person) return;
            var os_user = oc.os.getPersonData(person);
            if (classNames[i] == 'os_user_name') {
              element.html(os_user.name);
            } else if (classNames[i] == 'os_user_thumbnail_url') {
              element.attr('src', os_user.thumbnail_url);
            } else if (classNames[i] == 'os_user_background') {
              element.css('background-image', 'url(' + os_user.thumbnail_url+')');
            } else if (classNames[i] == 'os_user_profile_url') {
              if (element.attr('href')) {
                element.attr('href',os_user.profile_url);
              } else {
                element.html(os_user.profile_url);
              }
            }

          }
        });
      }
    });
  }

};

oc.canvas.data = {

  _fetchExtCB: null,
  _fetchFriendsWithApp: false,

  _fetch: function(request_id, require, callback)
  {
    var needData = false;
    var req = opensocial.newDataRequest();
    if(oc.os._viewer===null) {
      req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER), 'VIEWER');
      needData = true;
    }

    oc.canvas.data._curr_require = {};
    oc.canvas.data._curr_require.require_owner = oc.util.isArrayMember(require, oc.os.idspec.OWNER);
    oc.canvas.data._curr_require.require_owner_friends = oc.util.isArrayMember(require, oc.os.idspec.OWNER_FRIEND_IDS);
    oc.canvas.data._curr_require.require_viewer_friends = oc.util.isArrayMember(require, oc.os.idspec.VIEWER_FRIEND_IDS);

    if(oc.os._owner===null && oc.canvas.data._curr_require.require_owner) {
      req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER), 'OWNER');
      needData = true;
    }

    if(needData) {
      oc.canvas.data._fetchExtCB = callback;
      oc.os.sendDataRequest(req, function(dataResponse) {
        oc.canvas.data._fetchCB(request_id,dataResponse,callback);
      });
    } else {
      req = null;
    }

    return needData;
  },

  _fetchCB: function(request_id,dataResponse,callback)
  {
    if(dataResponse==oc.os.DataRequest.REQUEST_TIMED_OUT)  {
      oc.canvas.TIMED_OUT = true;
      oc.canvas.logRequest('REQUEST_TIMED_OUT:' + request_id);
      oc.canvas.data._fetchExtCB(request_id);
      return;
    }


    if(oc.os._checkData(dataResponse, 'OWNER')) {
      if(oc.os._owner = oc.os.getData(dataResponse, 'OWNER')) oc.os._addPerson(oc.os._owner);
    }

    if(oc.os._checkData(dataResponse, 'VIEWER')) {
      if(oc.os._viewer = oc.os.getData(dataResponse, 'VIEWER')) oc.os._addPerson(oc.os._viewer);
    }

    if (oc.os._lastError) {
      oc.canvas.TIMED_OUT = true;
      oc.canvas.logRequest(oc.os._lastError);
      oc.canvas.data._fetchExtCB(request_id);
      return;
    }

    if (oc.application.surface == 'canvas' && (oc.os._viewer == null || oc.os._viewer == false)) {
      oc.canvas.newUser = true;
    }

    oc.os._owner_is_viewer = oc.os._owner
    && oc.os._viewer
    && oc.os._owner.getId
    && oc.os._viewer.getId
    && oc.os._viewer.getId()==oc.os._owner.getId();

    if(oc.os._viewerFriends===null && (oc.canvas.data._curr_require.require_owner_friends || oc.canvas.data._curr_require.require_viewer_friends))
    {
      oc.canvas.data._fetchViewerFriends(request_id,callback);
    } else {
      callback(request_id);
    }
  },

  _fetchViewerFriends: function(request_id,callback)
  {
    oc.canvas.data._friendRequestCount = 0;
    oc.canvas.data._numFriendsFetched = 0;
    oc.canvas.data._numFriendsTotal = 0;
    oc.canvas.data._friendPageBeingFetched = -1;
    oc.canvas.data._fetchNextViewerFriendsPage(request_id,callback);
  },

  _fetchNextViewerFriendsPage: function(request_id,callback)
  {
    ++oc.canvas.data._friendPageBeingFetched;
    var req = opensocial.newDataRequest();
    oc.canvas.data._friendPageSize = 40;
    var params = {};
    params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = oc.os.idspec.PERSON;
    params[opensocial.DataRequest.PeopleRequestFields.FIRST] = oc.canvas.data._friendPageBeingFetched * oc.canvas.data._friendPageSize + 1;
    params[opensocial.DataRequest.PeopleRequestFields.MAX] = oc.canvas.data._friendPageSize;
    //opensocial.IdSpec.PersonId.VIEWER
    //var idspec = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" });
    
    if (oc.canvas.data._fetchFriendsWithApp == true) {
      params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP;
    } else {
      params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.ALL;
    }
    req.add(req.newFetchPeopleRequest(opensocial.DataRequest.Group.VIEWER_FRIENDS, params), 'viewer_friends_'+oc.canvas.data._friendPageBeingFetched);
    oc.os.sendDataRequest(req, function(dataResponse) {
      oc.canvas.data._fetchViewerFriendsPageCB(request_id,dataResponse,callback);
    });
  },

  _fetchViewerFriendsPageCB: function(request_id, dataResponse,callback) {
    if(dataResponse==oc.os.DataRequest.REQUEST_TIMED_OUT)  {
      oc.canvas.logRequest('REQUEST_TIMED_OUT:' + request_id);
      oc.canvas.data._fetchExtCB(request_id);
      return;
    }
    
    if(oc.os._checkData(dataResponse, 'viewer_friends_'+oc.canvas.data._friendPageBeingFetched)) {
      var fetchedFriends = oc.os.getData(dataResponse, 'viewer_friends_'+oc.canvas.data._friendPageBeingFetched);
      if(fetchedFriends) {

        if (oc.canvas.data._fetchFriendsWithApp == true) {
          if (oc.os._viewerFriendsWithApp == null) {
            oc.os._viewerFriendsWithApp = [];
            oc.canvas.data._numFriendsFetched = -1;
            oc.canvas.data._numFriendsTotal = fetchedFriends.getTotalSize();
          }
          fetchedFriends.each(function(person) {
            oc.os._hasAppStatus[person.getId()] = true;
            ++oc.canvas.data._numFriendsFetched
            oc.os._viewerFriendsWithApp.push(person);
          });

        } else {
          if (oc.os._viewerFriends == null) {
            oc.os._viewerFriends = [];
            oc.canvas.data._numFriendsFetched = -1;
            oc.canvas.data._numFriendsTotal = fetchedFriends.getTotalSize();
          }
          fetchedFriends.each(function(person) {
            oc.os._hasAppStatus[person.getId()] = false;
            oc.os._viewerFriends.push(person);
            oc.os._viewerFriendIds.push(person.getId());
            ++oc.canvas.data._numFriendsFetched
          });
          oc.os._addPeople(fetchedFriends);
          // rep to owner data if same person
          if(oc.os._owner_is_viewer) {
            oc.os._ownerFriends = oc.os._viewerFriends;
          }
        }
      }
    }
    if (oc.canvas.data._numFriendsTotal <= (oc.canvas.data._numFriendsFetched+1)) {
      if (oc.canvas.data._fetchFriendsWithApp == false) {
        oc.canvas.data._fetchFriendsWithApp = true;
        oc.canvas.data._fetchViewerFriends(request_id,callback);
      } else {
        callback(request_id);
      }
    } else {
      if (oc.canvas.data._friendRequestCount >= 100) {
        callback(request_id);
      } else {
        oc.canvas.data._fetchNextViewerFriendsPage(request_id,callback);
      }
      oc.canvas.data._friendRequestCount++;
    }
  }

};

oc.notification = {
  FAILED: 'FAILED',
  SUCCESS: 'SUCCESS',
  UNKNOWN: 'UNKNOWN',
  CANCELLED: 'CANCELLED',
  status: undefined,

  sendBulletin: function(message,title,callback){
    var os_token = MyOpenSpace.MySpaceContainer.OSToken;
    var osContainer = opensocial.Container.get();
    var new_message =opensocial.newMessage(message)
    new_message.setField(opensocial.Message.Field.TITLE,title)
    new_message.setField(opensocial.Message.Field.TYPE,MyOpenSpace.PostTo.Targets.BULLETINS)
    var res = osContainer.postTo(os_token, new_message,undefined,callback);
  },

  sendComment: function(recipient,message,callback) {
    var os_token = MyOpenSpace.MySpaceContainer.OSToken;
    var osContainer = opensocial.Container.get();
    var new_message =opensocial.newMessage(message)
    //new_message.setField(opensocial.Message.Field.TITLE,title)
    new_message.setField(opensocial.Message.Field.TYPE,MyOpenSpace.PostTo.Targets.COMMENTS)
    var res = osContainer.postTo(os_token, new_message,recipient,callback);
  },

  sendMessage: function(recipient,message,title,callback) {
    var os_token = MyOpenSpace.MySpaceContainer.OSToken;
    var osContainer = opensocial.Container.get();
    var new_message =opensocial.newMessage(message)
    new_message.setField(opensocial.Message.Field.TITLE,title)
    new_message.setField(opensocial.Message.Field.TYPE,MyOpenSpace.PostTo.Targets.SEND_MESSAGE)
    var res = osContainer.postTo(os_token, new_message,recipient,callback);
  },

  sendAppInvite: function(recipient,message,callback) {
    var inviteMessage = opensocial.newMessage(message);
    opensocial.requestShareApp(recipient.getField(opensocial.Person.Field.ID), inviteMessage, callback);
  }

};



