/**
 * 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");

var FlockOOBECookiePage = {
  // Hash of services added to UI

  BUNDLE_URI: "chrome://flock/locale/oobe/gettingStarted.properties",

  SERVICE_TYPE_PREFIX: "flock.oobe.serviceTypes.",
  SERVICE_TYPE_HEADER: ".header",

  // For media services, the login button won't be present; instead the button
  // will open the media bar a service's predefined media stream
  MEDIA_SVC_QUERY_PREFIX: "flock.oobe.mediaServices.",
  MEDIA_SVC_QUERY_SUFFIX: ".mediaQuery",

  // Each category should only display a maximum of 3 services
  CATEGORY_MAX_NUM_SVCS: 3,
  MAX_NUM_CATEGORIES: 3,

  PREF_SHOW_AT_STARTUP: "browser.startup.page",
  PREF_SHOW_SURVEY: "flock.welcome.show_survey",

  MYWORLD_URL: "about:myworld",
  BRAND_NAME: brandGetString("brand", "brandShortName"),
  METRICS_KEY_PREFIX: "GettingStarted-OOBE2"
};

/**
 * Return a string bundle
 */
FlockOOBECookiePage.getBundle =
function FlockOOBECookiePage_getBundle() {
  if (!this._bundle) {
    this._bundle = CC["@mozilla.org/intl/stringbundle;1"]
                   .getService(CI.nsIStringBundleService)
                   .createBundle(this.BUNDLE_URI);
  }
  return this._bundle;
};

/**
 * Returns an instance of flockIOOBECookieScan
 */
FlockOOBECookiePage.getCookieScanner =
function FlockOOBECookiePage_getCookieScanner() {
  if (!this._cookieScanner) {
    this._cookieScanner = CC["@flock.com/oobe-cookie-scan;1"]
                         .getService(CI.flockIOOBECookieScan)
                         .QueryInterface(CI.flockIOOBECookieScan);
  }
  return this._cookieScanner;
};

/**
 * Returns a flockIMetricsService instance
 */
FlockOOBECookiePage.getMetrics =
function FlockOOBECookiePage_getMetrics() {
  if (!this._metrics) {
    this._metrics = CC["@flock.com/metrics-service;1"]
                    .getService(CI.flockIMetricsService);
  }
  return this._metrics;
};

/**
 * Returns the preference service
 */
FlockOOBECookiePage.getPrefs =
function FlockOOBECookiePage_getPrefs() {
  if (!this._prefs) {
    this._prefs = CC["@mozilla.org/preferences-service;1"]
                  .getService(CI.nsIPrefBranch);
  }
  return this._prefs;
};

/**
 * Returns the observer service
 */
FlockOOBECookiePage.getObserverService =
function FlockOOBECookiePage_getObserverService() {
  if (!this._observerService) {
    this._observerService = CC["@mozilla.org/observer-service;1"]
                            .getService(CI.nsIObserverService);
  }
  return this._observerService;
};

/**
 * Returns the web detective service
 */
FlockOOBECookiePage.getWD =
function FlockOOBECookiePage_getWD() {
  if (!this._wd) {
    this._wd = CC["@flock.com/web-detective;1"]
               .getService(CI.flockIWebDetective);
  }
  return this._wd;
};

/**
 * Returns the account utilities service
 */
FlockOOBECookiePage.getACUtils =
function FlockOOBECookiePage_getACUtils() {
  if (!this._acUtils) {
    this._acUtils = CC["@flock.com/account-utils;1"]
                    .getService(CI.flockIAccountUtils);

  }
  return this._acUtils;
};

/**
 * Set the Mediabar search to a specific service
 */
FlockOOBECookiePage.setMediabarSearchService =
function FlockOOBECookiePage_setMediabarSearchService(aWindow, aSvcShortname) {
  if (aWindow && aWindow.mediabar && aSvcShortname) {
    aWindow.mediabar.searchService(aSvcShortname);
  }
};

/**
 * Opens the accounts and services sidebar to view all services
 */
FlockOOBECookiePage.openAccountsServicesSidebar =
function FlockOOBECookiePage_openAccountsServicesSidebar() {
  var wm = CC["@mozilla.org/appshell/window-mediator;1"]
           .getService(CI.nsIWindowMediator);
  var win = wm.getMostRecentWindow("navigator:browser");
  if (win) {
    // Only open, don't close if already open
    win.toggleSidebarWithMetric("flock_AccountsSidebarBroadcaster",
                                "AccountSidebar-Open",
                                null,
                                "GettingStartedViewAllServicesLink",
                                true);
  }
};

/**
 * Return an onclick action which opens the media bar
 * @param aServiceObject: Object containing a service's information such as:
 *                         type and service
 * aQuery: A media query to be executed for the service at hand
 */
FlockOOBECookiePage.openMediaStreamForService =
function FlockOOBECookiePage_openMediaStreamForService(aServiceObject,
                                                       aQuery)
{
  if (aServiceObject.service) {
    // Grab the media query label from service itself in case of change
    var svc = aServiceObject.service.QueryInterface(CI.flockIMediaWebService);
    var channels = svc.enumerateChannels();
    if (channels && channels.hasMoreElements()) {
      while (channels.hasMoreElements()) {
        var channel = channels.getNext().QueryInterface(CI.flockIMediaChannel);
        // The id of the channel equals the query itself
        if (channel.id == aQuery) {
          var wm = CC["@mozilla.org/appshell/window-mediator;1"]
                  .getService(CI.nsIWindowMediator);
          var win = wm.getMostRecentWindow("navigator:browser");
          if (win) {
            // Determine the state of the media bar
            if (!win.isSidebarOpen("flock_MediabarTopbarBroadcaster")) {
              var inst = this;
              var mediaBarDOMReaderObserver = {
                observe: function mediabar_Observe(aSubject, aTopic, aData) {
                  if (aTopic == "mediabarDOMReady") {
                    // Set the respective search engine
                    inst.setMediabarSearchService(win, svc.shortName);
                    // Remove the observer for cleanup
                    inst.getObserverService().removeObserver(this, aTopic);
                  }
                }
              };
              this.getObserverService().addObserver(mediaBarDOMReaderObserver,
                                                    "mediabarDOMReady",
                                                    false);

              // Open the media bar
              win.FlockTopbar.selectById("flock_MediabarTopbarBroadcaster",
                                         true);
            } else {
              this.setMediabarSearchService(win, svc.shortName);
            }

            // Load the service specific query
            win.mediabar.loadQuery(svc.shortName,
                                   channel.id,
                                   channel.title);
            // Report the usage
            this.getMetrics().report("MediaBar-Open",
                                     "GettingStartedMediaServiceClick");
          }
        }
      }
    }
  }
};

/**
 * Return a media query based on a service shortName
 * @param aSvcShortName:  shortName of the respective service
 */
FlockOOBECookiePage.getQueryForServiceShortName =
function FlockOOBECookiePage_getQueryForServiceShortName(aSvcShortName) {
  if (aSvcShortName) {
    return this.getBundle().GetStringFromName(this.MEDIA_SVC_QUERY_PREFIX
                                              + aSvcShortName
                                              + this.MEDIA_SVC_QUERY_SUFFIX);
  }
};

/**
 * Ping the metrics service that a service has been clicked
 * @param aServiceType: The type of service ie ("people", "media", etc)
 * @param aSvcShortName: shortName of the respective service
 */
FlockOOBECookiePage.reportServiceClicked =
function FlockOOBECookiePage_reportServiceClicked(aServiceType, aSvcShortName) {
  this.getMetrics().report(this.METRICS_KEY_PREFIX + "-ServiceClicked",
                           { service: aSvcShortName, type: aServiceType });
};

/**
 * Clears the document float
 * @param aParentNode: The respective parent to add a service node to
 * @param aServiceType: The type of service ie ("people", "media", etc)
 * @param aServiceObject: Object containing a service's information such as:
 *                        type and service
 */
FlockOOBECookiePage.addServiceNode =
function FlockOOBECookiePage_addServiceNode(aParentNode,
                                            aServiceType,
                                            aServiceObject)
{
  var bundle = this.getBundle();

  var acUtils = this.getACUtils();
  var svc = aServiceObject.service;

  // This checks for disabled services, ie flock.service.<name>.enabled=false
  // This works because you cannot instantiate a service, svc will be null.
  if (!(svc instanceof CI.flockIWebService)) {
    return;
  }

  // Report that the service has been added to the page
  this.getMetrics().report(this.METRICS_KEY_PREFIX + "-ServiceAdded",
                           { service: svc.shortName, type: aServiceType });

  var wd = this.getWD();

  // Create a container for the service node
  var container = document.createElement("div");
  container.setAttribute("class", "serviceLogoContainer");

  // Add the respective logo
  var serviceLogo = document.createElement("div");
  serviceLogo.setAttribute("class", "serviceLogo");
  serviceLogo.setAttribute("service", svc.shortName);
  container.appendChild(serviceLogo);

  // Onclick handler to open the service login page or the media bar
  var onclickFunction = function addServiceNode_dummy() { return null; }

  // Localized button verbiage
  var buttonText = "";

  switch (aServiceObject.type) {
    case "media":
      buttonText = bundle.GetStringFromName("flock.oobe.openMediaBar");
      var mediaQuery = this.getQueryForServiceShortName(svc.shortName);
      onclickFunction = function addServiceNode_mediaOnClick(aEvent) {
        FlockOOBECookiePage.reportServiceClicked(aServiceType, svc.shortName);
        FlockOOBECookiePage.openMediaStreamForService(aServiceObject,
                                                      mediaQuery);
      };
      break;

    default:
      buttonText = bundle.GetStringFromName("flock.oobe.serviceLoginText");
      if (svc.url) {
        onclickFunction = function addServiceNode_onClick(aEvent) {
          FlockOOBECookiePage.reportServiceClicked(aServiceType, svc.shortName);
          try {
            svc.logout();
          } catch (ex) {
            // Be defensive against a buggy getSessionCookies implementation
          }
          window.open(svc.url, "_blank");
        };
      }
      break;
  }

  // Add the action button, either a "Log in" or "Open Media Bar" button
  var actionButton = document.createElement("input");
  actionButton.setAttribute("type", "button");
  actionButton.setAttribute("class", "actionButton");
  actionButton.setAttribute("value", buttonText);
  container.appendChild(actionButton);

  // Register onclick handlers
  actionButton.addEventListener("click", onclickFunction, false);
  serviceLogo.addEventListener("click", onclickFunction, false);

  aParentNode.appendChild(container);
};


/**
 * Opens a Flock Feature
 */
FlockOOBECookiePage.openFlockFeature =
function FlockOOBECookiePage_openFlockFeature(aEvent, aType) {
  var wm = CC["@mozilla.org/appshell/window-mediator;1"]
          .getService(CI.nsIWindowMediator);
  var win = wm.getMostRecentWindow("navigator:browser");
  var metrics = this.getMetrics();

  switch (aType) {
    case "blog":
      // Open the blog editor
      if (win.flock_blog && win.flock_blog.service) {
        metrics.report("BlogEditor-Open", "GettingStarteBlogIconClicked");
        win.flock_blog.service.openEditor(null, null, null);
      }
      break;

    case "favorites":
    case "onlinefaves":
      // Open the favorites sidebar
      win.toggleSidebarWithMetric("viewBookmarksSidebar",
                                  "FavoritesSidebar-Open",
                                  null,
                                  "GettingStartedFavesIconClick",
                                  true);
      break;

    case "feeds":
      if (win.FlockFeeds) {
        // Open the feeds sidebar
        win.FlockFeeds.openSidebar("GettingStartedFeedsIconClick");
      }
      break;

    case "media":
      if (win.FlockTopbar) {
        // Open the mediabar
        win.FlockTopbar.selectById("flock_MediabarTopbarBroadcaster", true);
        metrics.report("MediaBar-Open", "GettingStartedMediaIconClick");
      }
      break;

    case "myworld":
      function _reportOpenMyWorld() {
        metrics.report("MyWorld-Open", "GettingStartedMyWorldIconClick");
      }
      if (win.gBrowser) {
        for (var i = 0; i < win.gBrowser.mTabs.length; i++) {
          var tabSpec = win.gBrowser.mTabs[i].linkedBrowser.currentURI.spec;
          if (tabSpec == "about:myworld") {
            win.gBrowser.selectedTab = win.gBrowser.mTabs[i];
            _reportOpenMyWorld();
            return;
          }
        }
      }
      // Open myworld in a new tab
      win.openUILinkIn(this.MYWORLD_URL, "tab");
      _reportOpenMyWorld();
      break;

    case "people":
      // Open the people sidebar
      win.toggleSidebarWithMetric("flockPeopleSidebarBroadcaster",
                                  "PeopleSidebar-Open",
                                  null,
                                  "GettingStartedPeopleIconClick",
                                  true);
      break;

    case "upload":
      if (win.FlockMedia) {
        // Launch the photo uploader
        metrics.report("Uploader-Open", "GettingStartedUploadIconClick");
        win.FlockMedia.getUploadSvc().launchUploader();
      }
      break;

    case "webmail":
      var webmailButton = win.document.getElementById("webmail-button");
      var webmailFlyout = win.document.getElementById("webmail-flyout");
      if (webmailButton && webmailFlyout) {
        // Show the webmail flyout
        metrics.report("Webmail-Open", "GettingStartedWebmailIconClick");
        webmailFlyout.showPopup(webmailButton,
                                -1,
                                -1,
                                "popup",
                                "bottomleft",
                                "topleft");
      }
      break;
  }
};

/**
 * Add a ServiceType ("people, "media", "webmail", "blog", "upload") containing
 * the type's respective services which the user has imported cookies for.
 * @param aParentNode: The respective parent to add a serviceType node to
 * @param aClassName:  The CSS className to assign the root serviceType node
 * @param aServiceTypeObject:  Object containing the serviceType's information
 * @param aServicesObjectArray:  Array of objects containing service specific
 *                               info (type and service)
 */
FlockOOBECookiePage.addServiceTypeNode =
function FlockOOBECookiePage_addServiceTypeNode(aParentNode,
                                                aClassName,
                                                aServiceTypeObject,
                                                aServicesObjectArray)
{
  var serviceType = document.createElement("div");
  serviceType.setAttribute("class", aClassName);
  serviceType.setAttribute("id", aServiceTypeObject.type);

  var servicePositioning = document.createElement("div");
  servicePositioning.setAttribute("class", "servicePositioning");
  serviceType.appendChild(servicePositioning);

  var serviceTypeDescriptor = document.createElement("div");
  serviceTypeDescriptor.setAttribute("class", "serviceTypeDescriptor");
  servicePositioning.appendChild(serviceTypeDescriptor);

  // Add the Icon and view link to the container
  var serviceTypeIconContainer = document.createElement("a");
  serviceTypeIconContainer.setAttribute("class", "serviceTypeIconContainer");
  serviceTypeDescriptor.appendChild(serviceTypeIconContainer);

  var serviceTypeIcon = document.createElement("div");
  serviceTypeIcon.setAttribute("class", "serviceTypeIcon");
  var serviceTypeIconOnClick = function serviceTypeIcon_OnClick(aEvent) {
    aEvent.stopPropagation();
    // Open the respective feature in the chrome
    FlockOOBECookiePage.openFlockFeature(aEvent, aServiceTypeObject.type);
  };
  serviceTypeIconContainer.addEventListener("click", serviceTypeIconOnClick, false);
  serviceTypeIconContainer.appendChild(serviceTypeIcon);

  var viewLink = document.createElement("a");
  viewLink.innerHTML = this.getBundle().GetStringFromName("flock.oobe.view");
  viewLink.setAttribute("class", "viewServiceType");
  serviceTypeIconContainer.appendChild(viewLink);

  var serviceTypeDetails = document.createElement("div");
  serviceTypeDetails.setAttribute("class", "serviceTypeDetails");
  serviceTypeDescriptor.appendChild(serviceTypeDetails);

  var headerText = document.createElement("h3");
  if (aServiceTypeObject && aServiceTypeObject.header) {
    var header = document.createTextNode(aServiceTypeObject.header);
    headerText.appendChild(header);
  }
  serviceTypeDetails.appendChild(headerText);

  if (aServicesObjectArray.length > 0) {
    // Iterate through the supplied service
    var servicesContainer = document.createElement("div");
    servicesContainer.setAttribute("class", "servicesContainer");
    servicePositioning.appendChild(servicesContainer);

    for (var i = 0; i < aServicesObjectArray.length; i++) {
      this.addServiceNode(servicesContainer,
                          aServiceTypeObject.type,
                          aServicesObjectArray[i]);
    }

    // Clear the float
    this.clearFloat(servicePositioning);
  }
  aParentNode.appendChild(serviceType);
};

FlockOOBECookiePage.getServiceTypeStringObject =
function FlockOOBECookiePage_getServiceTypeStringObject(aType) {
  var bundle = this.getBundle();
  var serviceTypeStringPrefix = this.SERVICE_TYPE_PREFIX + aType;
  var headerString = serviceTypeStringPrefix + this.SERVICE_TYPE_HEADER;
  // The brandShortName, could or could not be in the header strings;
  // replace its occurence instead of getStringFromBundle as we are unaware if
  // it is there
  return { type: aType,
           header: bundle.GetStringFromName(headerString)
                         .replace("%brandShortName%", this.BRAND_NAME) };
};

/**
 * Clears the document float
 * @param aParentNode:  The respective parent where the float will be cleared
 */
FlockOOBECookiePage.clearFloat =
function flockOOBECookiePage_clearFloat(aParentNode) {
  var clearFloat = document.createElement("div");
  clearFloat.setAttribute("class", "clearFloat");
  aParentNode.appendChild(clearFloat);
};

/**
 * Sets the "Show this at Startup" checkbox based on its preference
 */
FlockOOBECookiePage.setShowAtStartupCheckbox =
function FlockOOBECookiePage_setShowAtStartupCheckbox() {
  var prefs = this.getPrefs();
  var showCheckbox = document.getElementById("showAtStartUp");

  // Uncheck the checkbox only if the user has set unchecked the preference
  showCheckbox.checked = (prefs.getPrefType(this.PREF_SHOW_AT_STARTUP) &&
                          (prefs.getIntPref(this.PREF_SHOW_AT_STARTUP) == -1))
                       ? true
                       : false;
};

/**
 * Toggle the "Show this at Startup" checkbox based on the checkbox value
 * @param aCheckbox: DOM Checkbox
 */
FlockOOBECookiePage.toggleShowAtStartupCheckbox =
function FlockOOBECookiePage_toggleShowAtStartupCheckbox(aCheckbox) {
  // For the pref "browser.startup.page"
  // -1 = home + "Getting Started"
  // 0 = blank
  // 1 = home (browser.startup.homepage)
  // 2 = last visited page
  // 3 = resume previous browser session
  if (aCheckbox) {
    var prefValue =  (aCheckbox.checked) ? -1 : 1;
    this.getPrefs().setIntPref(this.PREF_SHOW_AT_STARTUP, prefValue);
  }
};

FlockOOBECookiePage.initSurvey =
function FlockOOBECookiePage_initSurvey() {
  var surveyDiv = document.getElementById("flockSurvey");
  var prefs = this.getPrefs();
  // The survey div is hidden by default. If the user has not clicked
  // on the survey link, we show the div.
  if (!prefs.getPrefType(this.PREF_SHOW_SURVEY) ||
      prefs.getBoolPref(this.PREF_SHOW_SURVEY))
  {
    var link = document.getElementById("surveyLink");
    var app = CC["@mozilla.org/xre/app-info;1"]
              .getService(CI.nsIXULAppInfo)
              .QueryInterface(CI.nsIXULRuntime);
    var url = "http://www.zoomerang.com/Survey/?p=WEB2292K27TRYC";
    link.setAttribute("href", url);
    link.setAttribute("target", "_blank");
    // Show the survey div.
    surveyDiv.setAttribute("style", "display: block;");
  }
};

FlockOOBECookiePage.viewDemoClick =
function FlockOOBECookiePage_viewDemoClick() {
  // Instrumentation
  var aChapter = "gettingStarted";
  CC["@flock.com/metrics-service;1"].getService(CI.flockIMetricsService)
    .report("OOBEDialog-Open", { Chapter: aChapter, source: "menuitem" });
 
  window.openDialog("chrome://flock/content/oobe/oobeDialog.xul",
                    this.getBundle().GetStringFromName("flock.oobe.welcome"),
                    "resizable=no,modal,centerscreen",
                    aChapter,
                    null);
};

FlockOOBECookiePage.surveyClick =
function FlockOOBECookiePage_surveyClick() {
  var prefs = this.getPrefs();
  prefs.setBoolPref(this.PREF_SHOW_SURVEY, false);
};

FlockOOBECookiePage.onLoad =
function FlockOOBECookiePage_onload(aEvent) {
  var inst = FlockOOBECookiePage;

  // Init the state of the "Show this at startup" checkbox
  inst.setShowAtStartupCheckbox();

  inst.initSurvey();

  var parentNode = document.getElementById("serviceTypesContainer");

  var servicesObjectArray;
  var numCategories = 0;
  var category;
  var categorySvcCount = 0;
  var className;

  var categoriesAddedHash = {};

  // Get the service data from the cookie scanner
  var serviceData = inst.getCookieScanner().getServiceData();

  for (var i = 0;
       (i < serviceData.length && numCategories < inst.MAX_NUM_CATEGORIES);
       i++)
  {
    // Initialize the variables
    servicesObjectArray = [];
    categorySvcCount = 0;
    category = serviceData[i].category;

    if (categoriesAddedHash[category]) {
      // Ensure the category is only ever added once.
      continue;
    }
    categoriesAddedHash[category] = true;
    numCategories++;

    for each (var svc in serviceData[i].services) {
      if (categorySvcCount < inst.CATEGORY_MAX_NUM_SVCS) {
        servicesObjectArray.push({ type: category,
                                   service: svc });
        categorySvcCount++;
      }
    }

    className = "serviceType";
    if (numCategories == inst.MAX_NUM_CATEGORIES) {
      className += " lastFeature";
    }
    inst.addServiceTypeNode(parentNode,
                            className,
                            inst.getServiceTypeStringObject(category),
                            servicesObjectArray);
  }

  // Clear the document float
  inst.clearFloat(parentNode);
};

window.onload = FlockOOBECookiePage.onLoad;
