/*
 * BEGIN FLOCK GPL
 *
 * Copyright Flock Inc. 2005-2009
 * 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 CU = Components.utils;

CU.import("resource:///modules/FlockStringBundleHelpers.jsm");
CU.import("resource:///modules/FlockPrefsUtils.jsm");

const REBUILD_ACCOUNT_DELAY = 3000;

const SERVICE_SHOW_PREF_BRANCH = "flock.notification.show.accounts";
const SERVICE_SHOW_PREF_HEADER = ".account-setup-info-";

const IS_TRANSIENT_RSC = "http://flock.com/rdf#isTransient";
const AUTH_TOKEN_RSC = "http://flock.com/rdf#authtoken";
const ACCOUNTS_ROOT_RSC = "http://flock.com/rdf#authtoken";

const BROWSER_HEIGHT_OFFSET = 50;

const FACEBOOK_CONTRACTID = "@flock.com/people/facebook;1";

var accountsSidebar = {
  sidebarObserver: null,

  gAccountsArea: ["people", "media", "bookmarks", "manualBlog", "webmail",
                  "instantMessage"],

  _metrics: CC["@flock.com/metrics-service;1"]
            .getService(CI.flockIMetricsService),

  services: null,

  prefService: CC["@mozilla.org/preferences-service;1"]
               .getService(CI.nsIPrefBranch),

  prefBranch: CC["@mozilla.org/preferences-service;1"]
              .getService(CI.nsIPrefService)
              .getBranch(SERVICE_SHOW_PREF_BRANCH),

  acctsService: CC["@flock.com/account-service;1"]
                .getService(CI.flockIAccountService),

  acctsObserver: null,

  acUtils: CC["@flock.com/account-utils;1"]
           .getService(CI.flockIAccountUtils),

  // Observer for the AccountsRoot rdf
  onAssert: function onAssert(aDatasource, aSource, aPredicate, aTarget) {
    if (aPredicate.Value == IS_TRANSIENT_RSC ||
        aPredicate.Value == AUTH_TOKEN_RSC)
    {
      accountsSidebar.rebuildAccounts();
    }
  },

  onUnassert: function onUnassert(aDatasource, aSource, aPredicate, aTarget) {
    if (aSource.Value == ACCOUNTS_ROOT_RSC) {
      accountsSidebar.rebuildAccounts();
    }
  },

  onChange: function onChange(aDatasource, aSource, aPredicate, aOldTarget,
                              aNewTarget)
  {
    switch (aPredicate.Value) {
      case IS_TRANSIENT_RSC:
        if (aNewTarget instanceof CI.nsIRDFLiteral) {
          // If we are "keeping" this account then delay the account refresh
          // to prevent user double-clicking and forgetting the account.
          if (aNewTarget.Value == "false") {
            // Delay rebuilding accounts so the user does not double-click.
            setTimeout("accountsSidebar.rebuildAccounts()",
                       REBUILD_ACCOUNT_DELAY);
          } else {
            accountsSidebar.rebuildAccounts();
          }
        }
        break;
    }
  },

  onMove: function onMove(aDS, aOldSource, aNewSource, aPredicate, aTarget) {
  },

  onBeginUpdateBatch: function onBeginUpdateBatch(aDatasource) {
  },

  onEndUpdateBatch: function onEndUpdateBatch(aDatasource) {
  },

  // Preference observer for the "flock.notification.show." branch
  observe: function as_observe(aSubject, aTopic, aData) {
    // Observe commands to select a service when opening
    if (aTopic == "accountsSidebar") {
      var availableServiceList = document.getElementById("availableServicesList");
      var folderList = availableServiceList.children;
      for (var iFolderCount = 0; iFolderCount < folderList.length; iFolderCount++) {
        var foundItem = false;
        var mFolder = document.getAnonymousElementByAttribute(folderList[iFolderCount],
                                                              "anonid", "title");
        if (mFolder.value == aData) {
          // They just want the folder open with no particular service selected.
          foundItem = true;
        } else {
          // Check if they want a service in this group
          var serviceList = folderList[iFolderCount].children;
          for (var iServiceCount = 0; iServiceCount < serviceList.length && !foundItem; iServiceCount++) {
            if (serviceList[iServiceCount].value == aData) {
              // We found a matching service so select and ensure that this is visible
              availableServiceList.clearSelection();
              serviceList[iServiceCount].selected = "true";
              availableServiceList.ensureElementIsVisible(serviceList[iServiceCount]);
              foundItem = true;
            }
          }
        }
        // Since the service we want is not in this area we need to close the folder
        // this way only the folder that has the service we want to highlight is open
        if (!foundItem) {
          folderList[iFolderCount].setAttribute("open", "false");
          folderList[iFolderCount].toggleOpen(null);
        } else {
          folderList[iFolderCount].setAttribute("open", "true");
        }
      }
      return;
    }

    // We can make this better by actually moving the child elements arround
    // rather than redrawing the whole tree again.
    if (aTopic == "nsPref:changed") {
      // data will be the "show.account-setup-info-" + svc.shortName
      this.loadAvailableServices();
    }

    if (aTopic == "toggleAccountsArea") {
      this.openAccountArea(aData);
    }

    if (aTopic == "highlightSvcsByInterface") {
      this.highlightSvcsByInterface(aData);
    }
  },

  QueryInterface: function QueryInterface(aIid) {
    if (!aIid.equals(CI.nsISupports) && !aIid.equals(CI.nsIObserver)) {
      throw Components.results.NS_ERROR_NO_INTERFACE;
    }
    return this;
  }
}

/**
 * Rebuild all accounts in sidebar.
 */
accountsSidebar.rebuildAccounts =
function as_rebuildAccounts() {
  document.getElementById("activeAccountsList").builder.rebuild();
  this.toggleEnabledAccounts();
}

accountsSidebar.toggleEnabledAccounts =
function as_toggleEnabledAccounts() {
  if (this.acUtils.doAccountsExist()) {
    document.getElementById("activeAccountsSectionDeck").selectedIndex = 0;
  } else {
    document.getElementById("activeAccountsSectionDeck").selectedIndex = 1;
  }
}

/**
 * Initialize the sidebar controls for Accounts and Services.
 *
 * This function is called when the Accounts and Services sidebar is loaded.
 * It loads and groups the available services in the Available Services tree
 * control.
 */
accountsSidebar.onLoad =
function as_onLoad() {
  this._metrics.report("AccountSidebar-Opened", null);

  this.prefBranch.QueryInterface(CI.nsIPrefBranch2);
  this.prefBranch.addObserver("", this, false);

  this._logger = CC["@flock.com/logger;1"].createInstance(CI.flockILogger);
  this._logger.init("accountsSidebar");
  this._logger.info("starting up...");

  // Bug 11962: Set a max height so that when enough configured accounts are
  // added the available accounts and services aren't pushed off the screen
  var windowHeight = window.innerHeight;
  if (windowHeight) {
    var maxHeight = windowHeight - BROWSER_HEIGHT_OFFSET;
    document.getElementById("activeAccountsSectionDeck")
            .setAttribute("maxheight", maxHeight);
  }

  // Load the coop so we can use it later.
  this.coop = CC["@flock.com/singleton;1"].getService(CI.flockISingleton)
              .getSingleton("chrome://flock/content/common/load-faves-coop.js")
              .wrappedJSObject;

  // So we can be localized
  this.strbundle = document.getElementById("accountStrings");

  // Get all the available services
  this.services = accountsSidebar.getFlockWebServices();

  // Load all available services
  this.loadAvailableServices();

  this.sidebarObserver = CC["@mozilla.org/observer-service;1"]
                         .getService(CI.nsIObserverService);
  this.sidebarObserver.addObserver(this, "accountsSidebar", false);
  this.sidebarObserver.addObserver(this, "toggleAccountsArea", false);
  this.sidebarObserver.addObserver(this, "highlightSvcsByInterface", false);

  // Set up observer for the flock-favorites
  var rdfService = CC["@mozilla.org/rdf/rdf-service;1"]
                   .getService(CI.nsIRDFService);

  var accountsDS = rdfService.GetDataSource("rdf:flock-favorites");
  accountsDS.AddObserver(accountsSidebar);

  this.toggleEnabledAccounts();

  // Notify observers that the sidebar has opened and is populated with data
  this.sidebarObserver.notifyObservers(null, "accountsServicesSidebarReady", null);

  this.acctsObserver = {
    onAccountAuthenticated:
    function accountsObs_onAccountAuthenticated(aAccount) {
      accountsSidebar.rebuildAccounts();
    },
    onAccountRemoved:
    function accountsObs_onAccountRemoved(aAccount) {
      accountsSidebar.rebuildAccounts();
    },
    onAccountUnauthenticated:
    function accountsObs_onAccountUnauthenticated(aAccount) {
      accountsSidebar.rebuildAccounts();
    },
    onAccountRefreshing:
    function accountsObs_onAccountRefreshing(aAccount) {
    },
    onAccountNoLongerRefreshing:
    function accountsObs_onAccountNoLongerRefreshing(aAccount) {
    }
  }
  this.acctsService.addObserver(this.acctsObserver);
}

/**
 * Shutdown the sidebar controls for Accounts and Services.
 *
 * This function is called when the Accounts and Services sidebar is unloaded.
 * It unregisters observers.
 */
accountsSidebar.onUnLoad =
function as_onUnload() {
  if (!this.sidebarObserver) {
    // not even loaded.
    return;
  }
  this._logger.info("onUnload");
  this._metrics.report("AccountSidebar-Close", null);

  var rdfService = CC["@mozilla.org/rdf/rdf-service;1"]
                   .getService(CI.nsIRDFService);

  var accountsDS = rdfService.GetDataSource("rdf:flock-favorites");
  accountsDS.RemoveObserver(accountsSidebar);

  this.prefBranch.removeObserver("", this, false);

  this.sidebarObserver.removeObserver(this, "accountsSidebar");
  this.sidebarObserver.removeObserver(this, "toggleAccountsArea");
  this.sidebarObserver.removeObserver(this, "highlightSvcsByInterface");
  this.acctsService.removeObserver(this.acctsObserver);

}

accountsSidebar.showPopup =
function as_showPopup(data) {
  var popup = document.getElementById("tipcontainer");

  // Remove old children
  while(popup.firstChild) {
    popup.removeChild(popup.firstChild);
  }

  var text = document.createTextNode(data);
  var desc = document.createElement("description");
  desc.appendChild(text);
  popup.appendChild(desc);

  popup.setAttribute("height", desc.boxObject.height + 5);
}

/**
 * Loads all available services.
 *
 * Load all available services in to the Available Services tree, and group
 * them by service type.
 */
accountsSidebar.loadAvailableServices =
function as_loadAvailableServices() {
  // Populates the active service list
  var availableServiceList = document.getElementById("availableServicesList");

  // Setup our groups
  var groupServiceArray = [];
  groupServiceArray["People"] = [];
  groupServiceArray["Media"] = [];
  groupServiceArray["Blog"] = [];
  groupServiceArray["Favorites"] = [];
  groupServiceArray["Webmail"] = [];
  groupServiceArray["Instant Messaging"] = [];

  // Clean the account list
  while (availableServiceList.getRowCount() > 0) {
    availableServiceList.removeItemAt(0);
  }

  function createAccountItem(aContractID, aSvc, aOverride) {
    var accountItem = document.createElement("richtreeitem");
    var accountLabel = document.createElement("label");
    var accountFavIcon = document.createElement("image");
    var accountBox = document.createElement("hbox");

    var title = aSvc.title;
    var tooltip = aSvc.tooltip;
    if (aOverride) {
      title = aOverride.title ? aOverride.title : title;
      tooltip = aOverride.tooltip ? aOverride.tooltip : tooltip;
    }

    accountItem.setAttribute("value", aContractID);
    accountBox.setAttribute("flex", "1");
    accountFavIcon.setAttribute("src", aSvc.icon);
    accountLabel.setAttribute("value", title);
    accountLabel.setAttribute("flex", "1");

    accountBox.appendChild(accountFavIcon);
    accountBox.appendChild(accountLabel);
    accountItem.appendChild(accountBox);

    if (aSvc.shortName != null) {
      // Set up the tooltip data
      accountItem.setAttribute("tooltip", "aas-tooltip");
      accountItem.setAttribute("onmouseover",
                               "accountsSidebar.showPopup(\"" + tooltip + "\")");
    }

    return accountItem;
  }

  // Loop through services to categorize them.
  for (var i = 0; i < this.services.length; i++) {
    var contractID = this.services[i][0];
    var svc = this.services[i][1];

    // Services that don't implement flockILoginWebService shouldn't appear.
    if (!(svc instanceof CI.flockILoginWebService)) {
      continue;
    }

    var accountitem = createAccountItem(contractID, svc);

    // Special case: We want to add Facebook under Instant Messaging as well as
    //               under the People category
    if (svc.contractId == FACEBOOK_CONTRACTID) {
      var override = {
        title: flockGetString("services/facebookchat", "facebookchat.title"),
        tooltip: flockGetString("services/facebookchat",
                                "facebookchat.tooltip",
                                ["Flock"])
      };
      var accountItemCopy = createAccountItem(contractID, svc, override);
      groupServiceArray["Instant Messaging"].push(accountItemCopy);
    }

    // NOTE: Order of services checking here is important! If a service
    //       implements more than 1 component (ie: both Blog and Media) then
    //       the first one checked here is where it will be categorized.

    if (svc instanceof CI.flockISocialWebService) {
      groupServiceArray["People"].push(accountitem);
      continue;
    }

    // Try and put it into the Blogging category
    // (Blogger, Blogsome, LiveJournal, Typepad, WordPress, Xanga...)
    if (svc instanceof CI.flockIBlogWebService) {
      groupServiceArray["Blog"].push(accountitem);
      continue;
    }

    // Next try the Media category (Flickr, Photobucket, YouTube...)
    if (svc instanceof CI.flockIMediaWebService) {
      groupServiceArray["Media"].push(accountitem);
      continue;
    }

    // Next try the bookmark category (Delicious...)
    if (svc instanceof CI.flockIBookmarkWebService) {
      groupServiceArray["Favorites"].push(accountitem);
      continue;
    }

    // Next try the webmail category (Yahoo! Mail, Gmail...)
    if (svc instanceof CI.flockIMailWebService) {
      groupServiceArray["Webmail"].push(accountitem);
      continue;
    }
  }

///////// Here is where we order the services into groups /////////

  // Social ("People") web services
  var accountFolder = document.createElement("richtreefolder");
  accountFolder.setAttribute("title",
                             this.strbundle.getString("flock.services.accountsSidebar.groups.people"));
  accountFolder.setAttribute("id",
                             "flock.services.accountsSidebar.groups.people");
  accountFolder.setAttribute("open", "true");
  if (groupServiceArray["People"].length > 0) {
    accountFolder.setAttribute("open", "true");
  }
  for (var i = 0; i < groupServiceArray["People"].length; i++) {
    accountFolder.appendChild(groupServiceArray["People"][i]);
  }
  availableServiceList.appendChild(accountFolder);

///////// BEGIN Media     //////////////
  var accountFolder = document.createElement("richtreefolder");
  accountFolder.setAttribute("title", this.strbundle.getString("flock.services.accountsSidebar.groups.media"));
  accountFolder.setAttribute("id", "flock.services.accountsSidebar.groups.media");
  accountFolder.setAttribute("open", "true");
  if (groupServiceArray["Media"].length > 0) {
    accountFolder.setAttribute("open", "true");
  }
  for (var i = 0; i < groupServiceArray["Media"].length; i++) {
    accountFolder.appendChild(groupServiceArray["Media"][i]);
  }
  availableServiceList.appendChild(accountFolder);
///////// END Media       //////////////

///////// BEGIN BLOGS //////////////
  var accountFolder = document.createElement("richtreefolder");
  accountFolder.setAttribute("title", this.strbundle.getString("flock.services.accountsSidebar.groups.blog"));
  accountFolder.setAttribute("id", "flock.services.accountsSidebar.groups.blog");
  accountFolder.setAttribute("open", "true");
  if (groupServiceArray["Blog"].length > 0) {
    accountFolder.setAttribute("open", "true");
  }
  for (var i = 0; i < groupServiceArray["Blog"].length; i++) {
    accountFolder.appendChild(groupServiceArray["Blog"][i]);
  }

  var accountitem = document.createElement("richtreeitem");
  var accountLabel = document.createElement("label");
  var accountFavIcon = document.createElement("image");
  var accountBox = document.createElement("hbox");

  // Add the special service for self-hosted blog
  accountitem.setAttribute("value", "CustomBlog");
  accountBox.setAttribute("flex", "1");
  accountFavIcon.setAttribute("class", "self-hosted-blog");
  accountLabel.setAttribute("value", this.strbundle.getString("flock.services.accountsSidebar.groups.manualBlog"));
  accountFolder.setAttribute("id", "flock.services.accountsSidebar.groups.manualBlog");
  accountLabel.setAttribute("flex", "1");
  accountLabel.setAttribute("tooltiptext", this.strbundle.getString("flock.services.accountsSidebar.tooltips.manualBlog"));
  accountBox.appendChild(accountFavIcon);
  accountBox.appendChild(accountLabel);
  accountitem.appendChild(accountBox);
  accountFolder.appendChild(accountitem);
  availableServiceList.appendChild(accountFolder);
///////// END BLOGS       //////////////

///////// BEGIN Bookmarks //////////////
  var accountFolder = document.createElement("richtreefolder");
  accountFolder.setAttribute("title", this.strbundle.getString("flock.services.accountsSidebar.groups.bookmarks"));
  accountFolder.setAttribute("id", "flock.services.accountsSidebar.groups.bookmarks");
  accountFolder.setAttribute("open", "true");
  if (groupServiceArray["Favorites"].length > 0) {
    accountFolder.setAttribute("open", "true");
  }
  for (var i = 0; i < groupServiceArray["Favorites"].length; i++) {
    accountFolder.appendChild(groupServiceArray["Favorites"][i]);
  }
  availableServiceList.appendChild(accountFolder);
///////// END Bookmarks   //////////////

  // Webmail services
  accountFolder = document.createElement("richtreefolder");
  accountFolder.setAttribute("title",
                             this.strbundle.getString("flock.services.accountsSidebar.groups.webmail"));
  accountFolder.setAttribute("id",
                             "flock.services.accountsSidebar.groups.webmail");
  accountFolder.setAttribute("open", "true");
  if (groupServiceArray["Webmail"].length > 0) {
    accountFolder.setAttribute("open", "true");
  }
  for (var i = 0; i < groupServiceArray["Webmail"].length; i++) {
    accountFolder.appendChild(groupServiceArray["Webmail"][i]);
  }
  availableServiceList.appendChild(accountFolder);

  // Instant Messaging services
  accountFolder = document.createElement("richtreefolder");
  accountFolder.setAttribute("title",
                             this.strbundle.getString("flock.services.accountsSidebar.groups.instantMessage"));
  accountFolder.setAttribute("id",
                             "flock.services.accountsSidebar.groups.instantMessage");
  accountFolder.setAttribute("open", "true");
  if (groupServiceArray["Instant Messaging"].length > 0) {
    accountFolder.setAttribute("open", "true");
  }
  for (var i = 0; i < groupServiceArray["Instant Messaging"].length; i++) {
    accountFolder.appendChild(groupServiceArray["Instant Messaging"][i]);
  }
  availableServiceList.appendChild(accountFolder);
}

/**
 * Loads all available services into an array.
 *
 * This loads all available services into an array of contractid and service
 * objects.
 */
accountsSidebar.getFlockWebServices =
function as_getFlockWebServices() {
  var topPeople  = FlockPrefsUtils.getCharPref("flock.accounts.top.people");
  var topMedia   = FlockPrefsUtils.getCharPref("flock.accounts.top.media");
  var topBlog    = FlockPrefsUtils.getCharPref("flock.accounts.top.blog");
  var topFaves   = FlockPrefsUtils.getCharPref("flock.accounts.top.favorite");
  var topWebmail = FlockPrefsUtils.getCharPref("flock.accounts.top.webmail");

  var CATMAN = CC["@mozilla.org/categorymanager;1"]
               .getService(CI.nsICategoryManager);
  var webServices = new Array();
  var e = CATMAN.enumerateCategory("flockWebService");
  while (e.hasMoreElements()) {
    try {
      var entry = e.getNext().QueryInterface(CI.nsISupportsCString);

      if (!entry) {
        continue;
      }

      var contractID = CATMAN.getCategoryEntry("flockWebService", entry.data);
      var svc = CC[contractID].getService(CI.flockIWebService);

      // Check to see if we should NOT show this in the list
      if (svc.isHidden()) {
        continue;
      }

      if ((svc.shortName == topPeople) ||
          (svc.shortName == topMedia) ||
          (svc.shortName == topBlog) ||
          (svc.shortName == topFaves) ||
          (svc.shortName == topWebmail))
      {
        webServices.unshift([contractID, svc]);
      } else {
        webServices.push([contractID, svc]);
      }
    } catch (e) {
      this._logger.info("Error occured in getFlockWebServices: " + e);
    }
  }
  return webServices;
}

/**
 * Go to a service's login page.
 *
 * This will navigate to the defined login page for a service when the user
 * double-clicks on an entry in the available services list.
 */
accountsSidebar.gotoServiceLoginPage =
function as_gotoServiceLoginPage(aEvent) {
  if (!document.getElementById("availableServicesList").selectedItem) {
    return;
  }
  var contractID = document.getElementById("availableServicesList")
                           .selectedItem
                           .value;

  switch (contractID) {
    case "CustomBlog":
      this._metrics.report("AccountSidebar-ServiceClick", contractID);
      // We need to open the custom blog editor instead
      window.openDialog("chrome://flock/content/blog/blogAccountWizard.xul",
                        "accountWizard",
                        "chrome,modal,centerscreen",
                        { defaultToCustom: true });
      accountsSidebar.rebuildAccounts();
      break;
    case "ApplyForService":
      // Here we just direct to a special url that the user can
      // request a service to add.
      // NOTE: Put this in a properties file!!! or better yet branding file
      var flockApplyForServiceUrl = "http://www.flock.com/";
      openUILinkIn(flockApplyForServiceUrl, "tab");
      break;
    default:
      var cid = CC[contractID];
      if (!cid) {
        // No cid exists, folder item or item is invalid.
        return;
      }

      var svc = cid.getService(CI.flockILoginWebService);
      this._metrics.report("AccountSidebar-ServiceClick", svc.shortName);
      if (svc) {
        var prefName = SERVICE_SHOW_PREF_BRANCH + SERVICE_SHOW_PREF_HEADER + svc.shortName;
        if (this.prefService.getPrefType(prefName) &&
            !this.prefService.getBoolPref(prefName))
        {
          // Re-enable this service
          this.prefService.setBoolPref(prefName, true);
        }
        var wsMgr = CC["@flock.com/webservice-manager;1"]
                    .getService(CI.flockIWebServiceManager);
        // Tell the Web Service Manager to automatically keep any accounts
        // created for this service during the next while...
        wsMgr.autoKeepAccountForService(svc.urn);

        // Display the login page for the service
        if (aEvent.button != 2) {
          var win = CC["@mozilla.org/appshell/window-mediator;1"]
                    .getService(CI.nsIWindowMediator)
                    .getMostRecentWindow("navigator:browser");
          win.FlockTabs.openURL(svc.url, aEvent);
        }
      }
      break;
    }

}

/**
 * Change Message
 *
 * This will change the message displayed directly above the available
 * accounts.  We have it in a function so that if we want we can add timers to
 * return to a default message.
 */
accountsSidebar.getNotificationBox =
function as_getNotificationBox() {
  var mainWindow = window.QueryInterface(CI.nsIInterfaceRequestor)
                         .getInterface(CI.nsIWebNavigation)
                         .QueryInterface(CI.nsIDocShellTreeItem)
                         .rootTreeItem
                         .QueryInterface(CI.nsIInterfaceRequestor)
                         .getInterface(CI.nsIDOMWindow);
  var gBrowser = mainWindow.getBrowser();
  return gBrowser.getNotificationBox();
}

accountsSidebar.clearNotifications =
function as_clearNotifications(aNotificationList) {
  var notificationBox = this.getNotificationBox();

  for (var iIndex = 0; iIndex < aNotificationList.length; iIndex++) {
    var oldNotification = notificationBox.getNotificationWithValue(aNotificationList[iIndex]);
    if (oldNotification) {
      notificationBox.removeNotification(oldNotification);
    }
  }
}


/**
 * Forget Account
 * This will remove the selected remembered account from the browser,
 * prompting the user before doing so.
 */
accountsSidebar.forgetAccount =
function as_forgetAccount(aAccountCard, aEvent) {

  // Ignore right mouse click
  if (aEvent.button == 2) {
    return;
  }

  var id = aAccountCard.parentNode.id;
  var account = this.coop.get(id);

  var prompts = CC["@mozilla.org/embedcomp/prompt-service;1"]
                .getService(CI.nsIPromptService);

  if (prompts.confirm(window,
                      this.strbundle
                          .getString("flock.services.accountsSidebar.remove.title") ,
                      this.strbundle
                          .getString("flock.services.accountsSidebar.remove.msg")))
  {
    var svc;
    var svcName;

    if (CC[account.serviceId]) {
      svc = CC[account.serviceId].getService(CI.flockIWebService);
      var customBlogTitle = null;
      if (svc instanceof CI.flockICustomBlogWebService) {
        // For custom blogs, the name of the service (metaweblog, atom...)
        // doesn't make sense, so we use the name of the blog
        customBlogTitle = account.name;
      }
      svcName = svc.shortName;
      svc.getAccount(id).logout(null);
      svc.removeAccount(id);
    } else {
      // The XPCOM service associated with this account does not currently
      // exist.  This probably means it was provided by an extension that has
      // been disabled or uninstalled.
      svcName = account.serviceId;
      var acUtils = CC["@flock.com/account-utils;1"]
                    .getService(CI.flockIAccountUtils);
      acUtils.removeAccount(account.id());
    }

    this._metrics.report("Account-Forget", svcName);

    this.clearNotifications(["account-setup-success-" + svcName,
                             "account-setup-info-" + svcName]);

    if (svc) {
      var nBox = this.getNotificationBox();
      var title = customBlogTitle ? customBlogTitle : svc.title;
      var message = this.strbundle
                    .getFormattedString("flock.services.accountsSidebar.removedAccount",
                                        [title]);
      nBox.appendNotification(message,
                              "account-remove-success-" + svcName,
                              "chrome://flock/skin/common/Info.png",
                              nBox.FLOCK_PRIORITY_LOW,
                              null,
                              null);
    }
  }
}

/**
 * Keep Account
 *
 * When a transient account is selected this will allow the user to keep said
 * account after restarts of the browser.
 */
accountsSidebar.keepAccount =
function as_keepAccount(aKeepButton) {
  // Disable the button, to prevent double clicks and forgetting the account.
  aKeepButton.setAttribute("disabled", true);

  // Get the account card
  var aAccountCard = document.getBindingParent(aKeepButton);

  var SB = "common/notificationOverlay";
  if (aAccountCard.parentNode.getAttribute("keepingaccount") == "true") {
    // We are in the process of keeping this account so don't allow
    // double-clicks.
    return;
  }

  var id = aAccountCard.parentNode.id;
  var account = this.coop.get(id);
  var svc = CC[account.serviceId].getService(CI.flockIWebService);
  svc.getAccount(id).keep();
}

/**
 * Navigate to account page.
 *
 * Opens the selected account's home page in a new tab.
 */
accountsSidebar.navigateToAccountPage =
function as_navigateToAccountPage(accountPageUrlLabel) {
  openUILinkIn(accountPageUrlLabel.getAttribute("urlLink"), "tab");
}

/**
 * Log into a service
 *
 * This will just navigate to the service page.
 */
accountsSidebar.logIn =
function as_logIn(aAccountCard, aEvent) {

  // Ignore right mouse click
  if (aEvent.button == 2) {
    return;
  }

  var urn = aAccountCard.parentNode.id;
  var coopAcct = this.coop.Account.get(urn);
  if (coopAcct) {
    var svc = CC[coopAcct.serviceId].getService(CI.flockIWebService);
    var account = svc.getAccount(urn);
    if (this.acUtils.ensureNoAuthenticatedAccountsBeforeLogin(account)) {
      openUILinkIn(svc.loginURL, "tab");
    }
  }
}

accountsSidebar.logout =
function as_logout(aAccountCard, aEvent) {

  // Ignore right mouse click
  if (aEvent.button == 2) {
    return;
  }

  this._logger.debug(".logout()");
  var id = aAccountCard.parentNode.id;
  var contractId = this.coop.Account.get(id).serviceId;
  var svc = CC[contractId].getService(CI.flockIWebService);
  svc.getAccount(id).logout(null);
}

/**
 * Takes a comma-delimited list of sidebar areas to reveal.  Any areas listed
 * in aRevealAreas will be expanded, and any other areas will be collapsed.
 */
accountsSidebar.openAccountArea =
function as_openAccountArea(aRevealAreas) {
  var revealArray = aRevealAreas.split(",");
  for each (var sbArea in this.gAccountsArea) {
    var sbAreaReveal = "false";
    for each (var revealArea in revealArray) {
      if (revealArea == sbArea) {
        sbAreaReveal = "true";
      }
    }
    document.getElementById("flock.services.accountsSidebar.groups." + sbArea)
            .setAttribute("open", sbAreaReveal);
  }
}

/**
 * Highlight all services given a specific interface
 */
accountsSidebar.highlightSvcsByInterface =
function as_highlightSvcsByInterface(aInterface) {
  // Get available services by interface
  var svcsEnum = this.acUtils.getWebServicesByInterface(aInterface);
  var mediaSvcContractID = [];
  while (svcsEnum.hasMoreElements()) {
    var svc = svcsEnum.getNext();
    // Push contractIDs for future reference
    mediaSvcContractID.push(svc.contractId);
  }

  // Highlight the respective DOM nodes
  var availableSvcs = document.getElementById("availableServicesList");
  var svcNodes = availableSvcs.getElementsByTagName("richtreeitem");
  for (var i = 0; i < svcNodes.length; i++) {
    var nodeContractID = svcNodes[i].getAttribute("value");
    for each (var contractID in mediaSvcContractID) {
      if (nodeContractID == contractID) {
        // Highlight the node on match
        svcNodes[i].setAttribute("highlight", "true");
      }
    }
  }
}

accountsSidebar.openBlogSettings =
function as_openBlogSettings(aAccountCard) {
  var id = aAccountCard.parentNode.id;
  var win = window.QueryInterface(CI.nsIInterfaceRequestor)
                  .getInterface(CI.nsIWebNavigation)
                  .QueryInterface(CI.nsIDocShellTreeItem)
                  .rootTreeItem
                  .QueryInterface(CI.nsIInterfaceRequestor)
                  .getInterface(CI.nsIDOMWindow);

  win.openDialog("chrome://flock/content/blog/blogAccountDlg.xul",
                 "editCustomBlog",
                 "modal,centerscreen",
                 { accountId: id });
}
