//
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2008
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
//

const CC = Components.classes;
const CI = Components.interfaces;
const CR = Components.results;

Components.utils.import("resource:///modules/FlockXPCOMUtils.jsm");
FlockXPCOMUtils.debug = false;

const MODULE_NAME = "Flock People Utils";

// People Utils
const FLOCK_PEOPLE_UTILS_CLASS_NAME = "Flock People Utils";
const FLOCK_PEOPLE_UTILS_CLASS_ID =
        Components.ID("{242d79d2-41d6-4a11-8949-7e4017ff7ef7}");
const FLOCK_PEOPLE_UTILS_CONTRACT_ID = "@flock.com/people-utils;1";

// Person
const FLOCK_PERSON_CLASS_NAME = "Flock Person";
const FLOCK_PERSON_CLASS_ID =
        Components.ID("{8c7b2681-b315-4c1b-b8dc-4d3d0fba003a}");
const FLOCK_PERSON_CONTRACT_ID = "@flock.com/person;1";


/**************************************************************************
 * Component: Flock People Utils
 **************************************************************************/

// Constructor.
function flockPeopleUtils() {
  this._coop = CC["@flock.com/singleton;1"]
               .getService(CI.flockISingleton)
               .getSingleton("chrome://flock/content/common/load-faves-coop.js")
               .wrappedJSObject;
  this._logger = CC["@flock.com/logger;1"]
                 .createInstance(CI.flockILogger);
  this._logger.init("peopleutils");
}

/**************************************************************************
 * Flock People Utils: XPCOM Component Creation
 **************************************************************************/

flockPeopleUtils.prototype = new FlockXPCOMUtils.genericComponent(
  FLOCK_PEOPLE_UTILS_CLASS_NAME,
  FLOCK_PEOPLE_UTILS_CLASS_ID,
  FLOCK_PEOPLE_UTILS_CONTRACT_ID,
  flockPeopleUtils,
  CI.nsIClassInfo.SINGLETON,
  [
    CI.flockIPeopleUtils,
  ]
);

/**************************************************************************
 * Flock People Utils: Private Data and Functions
 **************************************************************************/

flockPeopleUtils.prototype._getIdentityUrn =
function flockPeopleUtils__getIdentityUrn(aCoopAccount, aPersonId) {
  var coopService = aCoopAccount.service;
  var result = "urn:flock:identity:"
             + coopService.name.toLowerCase() + ":"
             + aCoopAccount.accountId + ":"
             + aPersonId;

  return result;
}

/**************************************************************************
 * Flock People Utils: flockIPeopleUtils Implementation
 **************************************************************************/

flockPeopleUtils.prototype.addPerson =
function flockPeopleUtils_addPerson(aAccount, aPerson) {
  var person = aPerson;

  var coopAccount = this._coop.get(aAccount.urn);

  // We include the current accountId in the identity urn to prevent friend
  // collisions if multiple accounts on the same service have the same friend.
  var identityUrn = this._getIdentityUrn(coopAccount, aPerson.accountId);
  var identity = this._coop.get(identityUrn);

  if (identity != null) {
    // Update the name if it has changed. We do this because some services do not
    // consider a name change to be an update and so we cannot use the lastUpdate
    // timestamp check to determine whether this field should be updated or not.
    if (person.name != identity.name) {
      identity.name = person.name;
    }

    // Did the person change? Theoretically we can just check lastupdate
    // however other properties can be out of synch especially during migration
    if (identity.lastUpdate >= person.lastUpdate &&
        identity.avatar == person.avatar &&
        identity.statusMessage == person.statusMessage &&
        identity.statusMessageUrl == person.statusMessageUrl && 
        identity.screenName == person.screenName &&
        identity.lastUpdateType == person.lastUpdateType &&
        identity.unseenMedia == person.unseenMedia &&
        identity.totalMedia == person.totalMedia)
    {
      // no update required.
      return identityUrn;
    }
    identity.URL = person.profileURL;
  } else {
    identity = new this._coop.Identity(
      identityUrn,
      {
        name: person.name,
        serviceId: coopAccount.service.serviceId,
        accountId: person.accountId,
        URL: person.profileURL
      }
    );
    if (!coopAccount.friendsList) {
      this.createFriendsList(aAccount.urn);
    }
    coopAccount.friendsList.children.add(identity);
  }
  // update data of the identity coop obj here
  identity.avatar = person.avatar;
  identity.statusMessage = person.statusMessage;
  identity.statusMessageUrl = person.statusMessageUrl;
  identity.screenName = person.screenName;
  identity.lastUpdateType = person.lastUpdateType;
  identity.unseenMedia = person.unseenMedia;
  identity.totalMedia = person.totalMedia;
  identity.lastUpdate = person.lastUpdate; // triggers the RDF observers

  return identityUrn;
}

flockPeopleUtils.prototype.removePerson =
function flockPeopleUtils_removePerson(aAccount, aPerson) {
  var coopAccount = this._coop.get(aAccount.urn);
  var identityUrn = this._getIdentityUrn(coopAccount, aPerson.accountId);

  var coopIdentity = this._coop.get(identityUrn);
  if (coopIdentity) {
    coopIdentity.destroy();
  } else {
    this._logger.error("Can't remove "
                       + identityUrn
                       + ": it doesn't exist!");
  }
}

flockPeopleUtils.prototype.getPerson =
function flockPeopleUtils_getPerson(aPersonUrn) {
   this._logger.info("getPerson('"+ aPersonUrn + "')");
   
  var person = null;
  if (this._coop.Identity.exists(aPersonUrn)) {
    var coopPerson = this._coop.get(aPersonUrn);
    person = CC["@flock.com/person;1"]
               .createInstance(CI.flockIPerson);
    person.accountId = coopPerson.accountId;
    person.lastUpdate = coopPerson.lastUpdate;
    person.lastUpdateType = coopPerson.lastUpdateType;
    person.name = coopPerson.name;
    person.avatar = coopPerson.avatar;
    person.statusMessage = coopPerson.statusMessage;
    person.statusMessageUrl = coopPerson.statusMessageUrl;
    person.profileURL = coopPerson.URL;
    person.screenName = coopPerson.screenName;
    person.unseenMedia = coopPerson.unseenMedia;
    person.totalMedia = coopPerson.totalMedia;
  }
  return person;
}

flockPeopleUtils.prototype.incrementMedia =
function flockPeopleUtils_incrementMedia(aAccount,
                                         aPersonId,
                                         aCount,
                                         aLatest)
{
  // Update the count on the identity...
  aCoopAccount = this._coop.get(aAccount.urn);
  var identityUrn = this._getIdentityUrn(aCoopAccount, aPersonId);
  var coopIdentity = this._coop.get(identityUrn);
  coopIdentity.unseenMedia += aCount;

  // + 10 explanation: when the friend uploads a new photo, Facebook
  // updates the profile update time a few seconds after the photo upload.
  // We want that to show as a "media" update, not as a "profile" update
  if ((aLatest + 10) >= coopIdentity.lastUpdate) {
    coopIdentity.lastUpdate = new Date(aLatest);
    coopIdentity.lastUpdateType = "media";
  }
}

/**************************************************************************
 * END Flock People Utils
 **************************************************************************/


/**************************************************************************
 * BEGIN Flock Person
 **************************************************************************/

// Constructor.
function flockPerson() {
}

/**************************************************************************
 * Flock Person: XPCOM Component Creation
 **************************************************************************/

flockPerson.prototype = new FlockXPCOMUtils.genericComponent(
  FLOCK_PERSON_CLASS_NAME,
  FLOCK_PERSON_CLASS_ID,
  FLOCK_PERSON_CONTRACT_ID,
  flockPerson,
  CI.nsIClassInfo.SINGLETON,
  [
    CI.flockIPerson,
  ]
);

flockPerson.prototype.urn = "";
flockPerson.prototype.serviceId = "";
flockPerson.prototype.accountId = "";
flockPerson.prototype.avatar = "";
flockPerson.prototype.name = "";
flockPerson.prototype.statusMessage = "";
flockPerson.prototype.statusMessageUrl = "";
flockPerson.prototype.lastUpdate = 0;
flockPerson.prototype.lastUpdateType = "";
flockPerson.prototype.unseenMedia = 0;
flockPerson.prototype.totalMedia = 0;
flockPerson.prototype.lastUploadedMedia = 0;
flockPerson.prototype.profileURL = "";
flockPerson.prototype.screenName = "";

/**************************************************************************
 * END Flock Person
 **************************************************************************/


/**************************************************************************
 * XPCOM Support - Module Construction
 **************************************************************************/

// Create array of components.
var gComponentsArray = [flockPeopleUtils, flockPerson];

// Generate a module for XPCOM to find.
var NSGetModule = FlockXPCOMUtils.generateNSGetModule(MODULE_NAME,
                                                      gComponentsArray);

/**************************************************************************
 * END XPCOM Support
 **************************************************************************/
