const nsISupports           = Components.interfaces.nsISupports;
const nsICategoryManager    = Components.interfaces.nsICategoryManager;
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
const nsICommandLine        = Components.interfaces.nsICommandLine;
const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
const nsIFactory            = Components.interfaces.nsIFactory;
const nsIModule             = Components.interfaces.nsIModule;
const nsIWindowWatcher      = Components.interfaces.nsIWindowWatcher;


const appStartup = Components.classes['@mozilla.org/toolkit/app-startup;1'].
    getService(Components.interfaces.nsIAppStartup);


// category names are sorted alphabetically. Typical command-line handlers use a
// category that begins with the letter "m".
const clh_category = "yoono-desktop-cl";

const clh_contractID = "@mozilla.org/commandlinehandler/general-startup;1?type="+clh_category;

const clh_CID = Components.ID("{430CA0E4-9D44-11DE-81DD-6E8055D89593}");

/**
 * Utility functions
 */

/**
 * The XPCOM component that implements nsICommandLineHandler.
 * It also implements nsIFactory to serve as its own singleton factory.
 */
function myComponent() {
}
myComponent.prototype = {
  // this must match whatever is in chrome.manifest!
  classID: Components.ID("{430CA0E4-9D44-11DE-81DD-6E8055D89593}"),

  /* nsISupports */
  QueryInterface : function clh_QI(iid)
  {
    if (iid.equals(nsICommandLineHandler) ||
        iid.equals(nsIFactory) ||
        iid.equals(nsISupports))
      return this;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  wrappedJSObject : this,
  lastCommand : null,

  uninstall : function () {
    Components.utils.import("resource://yoono/yoonoYEXTIF.js");
    Components.utils.import("resource://yoono/yoonoService.js");
    Components.utils.import("resource://yoono/yoonoLog.js");
    Components.utils.import("resource://yoono/yoonoDialogs.js");
    Components.utils.import("resource://yoono/yoonoUtils.js");
    Components.utils.import("resource://yoono/yoonoPrefs.js");
    Components.utils.import("resource://yoono/yoonoSidebarService.js");
    Components.utils.import("resource://yoono/yoonoStorage.js");
    Components.utils.import("resource://yoono/yoonoKeyValueDB.js");

    Components.utils.reportError("uninstall ... ");
    var yoono = {};
    yoono.log=YOONO_LOG;
    yoono.utils=YOONO_UTILS;
    yoono.server = {
      launch : function (a,b) {
        // Called by YEXTIF when user is registered
        // with arguments ("connect", "no-sync")
        dump("Try to call launch with args : "+a+','+b+'\n');
      }
    }
    yoono.prefs=YOONO_PREFS;
    yoono.yextif=YOONO_YEXTIF;
    yoono.sidebar=YOONO_SIDEBAR;

    yoono.main=YOONO_CMPT;
    yoono.bkm = {start:function(){}};
    yoono.dialogs=YOONO_DIALOGS;
    yoono.storage=YOONO_STORAGE;

    YOONO_LOG.init(yoono);
    YOONO_PREFS.init(yoono);
    YOONO_DIALOGS.init(yoono);
    YOONO_CMPT.init(yoono);
    YOONO_SIDEBAR.init(YOONO_CMPT);
    YOONO_YEXTIF.init(yoono);
    YOONO_STORAGE.init(yoono);

    // Change YEXTIF specifics methods dynamically
    YOONO_YEXTIF.methods.isStandalone = function () {return 1;};
    YOONO_YEXTIF.methods.getClientType = function () {return "dsk";};
    YOONO_YEXTIF.methods.getVersion = function () {
      var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
      return appInfo.version;
    };

    // Open uninstall dialog
    var goodbyeWizardReturnObject={};
    var array = Components.classes["@mozilla.org/array;1"]
                          .createInstance(Components.interfaces.nsIMutableArray);
    var variant = Components.classes["@mozilla.org/variant;1"]
                            .createInstance(Components.interfaces.nsIWritableVariant);
    variant.setFromVariant(goodbyeWizardReturnObject);
    array.appendElement(variant, false);
    var windowWatcher = Components.classes['@mozilla.org/embedcomp/window-watcher;1']
            .getService(Components.interfaces.nsIWindowWatcher);
    windowWatcher.openWindow(
        null, 'chrome://yoono/content/dialogs/goodbye.xul',
        'navigator:browser', 'chrome,resizable=yes,dialog=yes,titlebar=yes,modal=yes', array)

    if (!goodbyeWizardReturnObject.value) return Components.utils.reportError("... uninstall canceled!");;

    var serverurl = YOONO_PREFS.get('serverurl');

    // Send uninstall request
    try {
      var script = goodbyeWizardReturnObject.script;
      var reqResult = YOONO_CMPT.sendRequest(serverurl + 'linkserver', 'POST', 'sync', script, null);

      var response = reqResult[1];
      var message = response['display-error'].@code;
      if('ERROR_INVALID_USER_ID' == message) {
      }
      message = response['display-message'].@code.toString();
      // TO BE DONE : what is best in case account could not be deleted ?
      switch(message) {
        case 'MSG_USER_ACCOUNT_REMOVED':
           // SUCCESSDELETED.hidden = false;
        break;
        case 'MSG_USER_ACCOUNT_NOT_REMOVED':
           // SUCCESSKEPT.hidden = false;
        break;
        default:
      }
    } catch(e) {
      Components.utils.reportError(e);
    }

    // Flush stats
    try {
      YOONO_CMPT.checkStats('uninstall');
    } catch(e) {
      Components.utils.reportError(e);
    }

    // Cleanup
    try {
      YOONO_CMPT.uninstall();
    } catch(e) {
      Components.utils.reportError(e);
    }

    Components.utils.reportError("... uninstall ok!");
  },


  /* nsICommandLineHandler */

  handle : function clh_handle(cmdLine)
  {


    if(cmdLine.handleFlag('uninstall', false)) {

      this.uninstall();
      cmdLine.preventDefault = true;

    } else {

      var windowWatcher = Components.classes['@mozilla.org/embedcomp/window-watcher;1']
            .getService(Components.interfaces.nsIWindowWatcher);

      var windowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1']
          .getService(Components.interfaces.nsIWindowMediator);

      var window = windowMediator.getMostRecentWindow('navigator:browser');
      if(window)
        window.focus();
      else
        windowWatcher.openWindow(
              null, 'chrome://yoonorunner/content/main.xul',
              'navigator:browser', 'chrome,resizable=yes', null);

    }
  },

  helpInfo : "",


  /* nsIFactory */

  createInstance : function clh_CI(outer, iid)
  {
    if (outer != null)
      throw Components.results.NS_ERROR_NO_AGGREGATION;

    return this.QueryInterface(iid);
  },

  lockFactory : function clh_lock(lock)
  {
    /* no-op */
  }
};

/**
 * The XPCOM glue that implements nsIModule
 */
const myAppHandlerModule = {
  /* nsISupports */
  QueryInterface : function mod_QI(iid)
  {
    if (iid.equals(nsIModule) ||
        iid.equals(nsISupports))
      return this;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  /* nsIModule */
  getClassObject : function mod_gch(compMgr, cid, iid)
  {
    if (cid.equals(clh_CID))
      return myComponent.prototype.QueryInterface(iid);

    throw Components.results.NS_ERROR_NOT_REGISTERED;
  },

  registerSelf : function mod_regself(compMgr, fileSpec, location, type)
  {
    compMgr.QueryInterface(nsIComponentRegistrar);

    compMgr.registerFactoryLocation(clh_CID,
                                    "myAppHandler",
                                    clh_contractID,
                                    fileSpec,
                                    location,
                                    type);

    var catMan = Components.classes["@mozilla.org/categorymanager;1"].
      getService(nsICategoryManager);
    catMan.addCategoryEntry("command-line-handler",
                            clh_category,
                            clh_contractID, true, true);
  },

  unregisterSelf : function mod_unreg(compMgr, location, type)
  {
    compMgr.QueryInterface(nsIComponentRegistrar);
    compMgr.unregisterFactoryLocation(clh_CID, location);

    var catMan = Components.classes["@mozilla.org/categorymanager;1"].
      getService(nsICategoryManager);
    catMan.deleteCategoryEntry("command-line-handler", clh_category);
  },

  canUnload : function (compMgr)
  {
    return true;
  }
};

try {
  Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  var NSGetFactory = XPCOMUtils.generateNSGetFactory([myComponent]);
} catch(e) {
  /* The NSGetModule function is the magic entry point that XPCOM uses to find what XPCOM objects
   * this component provides
   */
  function NSGetModule(comMgr, fileSpec)
  {
    return myAppHandlerModule;
  }
}
