//
// 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 SM_CONTRACTID = '@flock.com/search-migratable;1';
const SM_CLASSID    = Components.ID('{24ddbfe0-4216-40cb-a037-2c17ab7d5a47}');
const SM_CLASSNAME  = 'Flock Search Service Migratable';

const ELSEWHERE_ENGINES_PREF = "flock.search.elsewhereEngines";
const SEARCHELSEWHERE_EXCLUSION_PREF  = "flock.search.excludedEngines";
const SEARCHELSEWHERE_EXCLUSION_LIST ="Yahoo!,eBay,Technorati,Wink People";
const PREF_LIVESEARCH_ENABLED_SVCS = "flock.liveSearch.enabledServices";
const PREF_LIVESEARCH_ORDERED_SVCS = "flock.liveSearch.orderedServices";
const SHOWFAVORITES_PREF = "flock.search.flyout.showFavorites";
const SHOWHISTORY_PREF = "flock.search.flyout.showHistory";
const SHOWYAHOORESULTS_PREF = "flock.search.flyout.showYahooLiveResults";

const KEYWORD_URL_PREF = "keyword.URL";
const KEYWORD_PROVIDER_PREF = "flock.keyword.provider";

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;

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


function SearchMigratable() {
}

SearchMigratable.prototype = {
  get migrationName() {
    return flockGetString("common/migrationNames", "migration.name.search");
  },

  needsMigration: function SM_needsMigration(oldVersion) {
    var versionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"]
                         .getService(Ci.nsIVersionComparator);

    if (versionChecker.compare(oldVersion, "2.0b4") < 0) {
      if (versionChecker.compare(oldVersion, "1.0") < 0) {
        if (FlockPrefsUtils.prefHasUserValue(SHOWFAVORITES_PREF) ||
            FlockPrefsUtils.prefHasUserValue(SHOWHISTORY_PREF) ||
            FlockPrefsUtils.prefHasUserValue(SHOWYAHOORESULTS_PREF)) {
          return true;
        }
      }
      return !FlockPrefsUtils.prefHasUserValue(ELSEWHERE_ENGINES_PREF)
             || FlockPrefsUtils.prefHasUserValue(KEYWORD_URL_PREF);
    } else {
      return versionChecker.compare(oldVersion, "2.5") < 0;
    }
  },
  startMigration: function SM_startMigration(oldVersion, listener) {
    var versionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"]
                         .getService(Ci.nsIVersionComparator);

    var enabled = FlockPrefsUtils.getCharPref(PREF_LIVESEARCH_ENABLED_SVCS)
                                 .split(",");

    if (versionChecker.compare(oldVersion, "0.8") < 0) {
      // If both favorites and history are disabled, disable flock livesearch.
      var flock_pref = FlockPrefsUtils.getBoolPref(SHOWFAVORITES_PREF);
      if (!flock_pref) {
        flock_pref = FlockPrefsUtils.getBoolPref(SHOWHISTORY_PREF);
      }
      if (!flock_pref) {
        var filterFlockFunc = function SM_filterFlockFunc(aElem, aIdx, aArray) {
          return (aElem != "flock");
        };
        enabled = enabled.filter(filterFlockFunc);
      }
  
      // Disable yahoo live results if previously disabled.
      var yahoo_pref = FlockPrefsUtils.getBoolPref(SHOWYAHOORESULTS_PREF);
      if (!yahoo_pref) {
        var filterYahooFunc = function SM_filterYahooFunc(aElem, aIdx, aArray) {
          return (aElem != "yahoo");
        };
        enabled = enabled.filter(filterYahooFunc);
      }
    }

    var excluded = FlockPrefsUtils.getCharPref(SEARCHELSEWHERE_EXCLUSION_PREF);
    excluded = excluded ? excluded : SEARCHELSEWHERE_EXCLUSION_LIST;
    var included = [];
    if (versionChecker.compare(oldVersion, "2.0b4") < 0) {

      var searchEngines = Cc["@mozilla.org/browser/search-service;1"]
                          .getService(Ci.nsIBrowserSearchService).getEngines({});
      for each (var engine in searchEngines) {
        included.push(engine.name);
      }
    }

    if (versionChecker.compare(oldVersion, "2.5") < 0) {
      var ordered = FlockPrefsUtils.getCharPref(PREF_LIVESEARCH_ORDERED_SVCS);
      if (ordered && ordered.indexOf("twitter,") == -1) {
        FlockPrefsUtils.setCharPref(PREF_LIVESEARCH_ORDERED_SVCS,
                                    ordered + "twitter,");
      }
    }

    var ctxt = {
      listener: listener,
      oldVersion: oldVersion,
      versionChecker: versionChecker,

      oldExcluded: excluded ? excluded.split(",") : [],
      newIncluded: included,
      newEnabled: enabled
    };

    return { wrappedJSObject: ctxt };
  },
  finishMigration: function SM_finishMigration(ctxtWrapper) {
    var ctxt = ctxtWrapper.wrappedJSObject;

    if (ctxt.versionChecker.compare(ctxt.oldVersion, "2.0b4") < 0) {
      FlockPrefsUtils.setCharPref(ELSEWHERE_ENGINES_PREF,
                                  ctxt.newIncluded.join());
      if (FlockPrefsUtils.prefHasUserValue(SEARCHELSEWHERE_EXCLUSION_PREF)) {
        FlockPrefsUtils.clearPref(SEARCHELSEWHERE_EXCLUSION_PREF);
      }

      if (FlockPrefsUtils.prefHasUserValue(KEYWORD_URL_PREF)) {
        var keywordURL = FlockPrefsUtils.getCharPref(KEYWORD_URL_PREF);
        if (!keywordURL.match(/yahoo.com/i)) {
          FlockPrefsUtils.setCharPref(KEYWORD_PROVIDER_PREF, keywordURL);
        }
      }
    }

    if (ctxt.versionChecker.compare(ctxt.oldVersion, "0.8") < 0) {
      FlockPrefsUtils.setCharPref(PREF_LIVESEARCH_ENABLED_SVCS,
                                  ctxt.newEnabled.join());
    }
  },
  doMigrationWork: function SM_doMigrationWork(ctxtWrapper) {
    var ctxt = ctxtWrapper.wrappedJSObject;

    var oldEngine = ctxt.oldExcluded.shift();
    var newEngine;

    if (ctxt.versionChecker.compare(ctxt.oldVersion, "0.8") < 0) {
      var replaceFunc = function SM_cardinalEngineReplace(aMatch, a1, aStr) {
        if (!a1) {
          return "";
        }
        var newEngine = a1;
        switch (a1) {
          case "jeeves":
            newEngine = "Ask.com";
          break;
          case "winkflock":
            newEngine = "Wink People";
          break;
          case "wikipedia":
            newEngine = "Wikipedia";
          break;
          case "eBay":
            newEngine = "eBay";
          break;
          case "jajah":
            newEngine = "Jajah Telephony";
          break;
          case "bittorrent":
            newEngine = "BitTorrent";
          break;
          case "blogger":
            newEngine = "Blogger Blog Search";
          break;
          case "craigslist_forsale":
            newEngine = "Craigs List For Sale";
          break;
          case "del.icio.us":
            newEngine = "del.icio.us tag";
          break;
          case "dictionary":
            newEngine = "Dictionary.com";
          break;
          case "espn":
            newEngine = "ESPN";
          break;
          case "foodtv":
            newEngine = "Food Network Recipes";
          break;
          case "googleimages":
            newEngine = "Google Images";
          break;
          case "hollywoodvideo":
            newEngine = "HollyWood Video Search";
          break;
          case "itunesuk":
            newEngine = "iTunes Music Store";
          break;
          case "linkedin-bf":
            newEngine = "LinkedIn";
          break;
          case "lj-int":
            newEngine = "Livejournal Interest";
          break;
          case "lonelyplanet":
            newEngine = "Lonely Planet Online";
          break;
          case "marketwatch":
            newEngine = "MarketWatch";
          break;
          case "pg":
            newEngine = "PriceGrabber";
          break;
          case "urbandictionary":
            newEngine = "UrbanDictionary.com";
          break;
          case "weather":
            newEngine = "weather.com";
          break;
          case "amazondotcom":
            newEngine = "Amazon.com";
          break;
          case "expediadotcom":
            newEngine = "Expedia.com";
          break;
          case "youtube":
            newEngine = "youtube";
          break;
          case "myspace":
            newEngine = "Myspace.com";
          break;
          case "xanga":
            newEngine = "Xanga.com";
          break;
          default:
            if (a1.indexOf("babelfish_") == 0) {
              var langs = a1.substr(a1.indexOf("_") + 1).split("2");
              var lang0 = langs[0].charAt(0).toUpperCase() + langs[0].substr(1);
              var lang1 = langs[1].charAt(0).toUpperCase() + langs[1].substr(1);
              
              newEngine = "Babel Fish " + lang0 + "->" + lang1;
            } else { //Yahoo, Google, Technorati, Shadows, Facebook, Gmail,
                     //IMDb, MSN, Yahooligans
              newEngine = a1.charAt(0).toUpperCase() + a1.substr(1);
            }
          break;
        }
        return newEngine;
      };
      newEngine =
        oldEngine.replace(/NC:SearchCategory\?engine=urn:search:engine:(.+)\.src/,
                          replaceFunc);
    } else {
      newEngine = oldEngine;
    }

    if (newEngine) {
      if (newEngine == "Yahoo") {
        newEngine = "Yahoo!";
      }

      if (ctxt.versionChecker.compare(ctxt.oldVersion, "2.0b4") < 0) {
        var i = 0;
        while (i < ctxt.newIncluded.length) {
          if (ctxt.newIncluded[i].toLowerCase() == newEngine.toLowerCase()) {
            ctxt.newIncluded.splice(i, 1);
            break;
          }
          i++;
        }
      }
    }

    return Boolean(ctxt.oldExcluded.length);
  },

  getInterfaces: function SM_getInterfaces(countRef) {
    var interfaces = [Ci.flockIMigratable, Ci.nsIClassInfo, Ci.nsISupports];
    countRef.value = interfaces.length;
    return interfaces;
  },
  getHelperForLanguage: function SM_getHelperForLanguage(language) {
    return null;
  },
  contractID: SM_CONTRACTID,
  classDescription: SM_CLASSNAME,
  classID: SM_CLASSID,
  implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
  flags: Ci.nsIClassInfo.SINGLETON,

  QueryInterface: function SM_QueryInterface(iid) {
    if (iid.equals(Ci.flockIMigratable) ||
        iid.equals(Ci.nsIClassInfo) ||
        iid.equals(Ci.nsISupports))
      return this;
    throw Cr.NS_ERROR_NO_INTERFACE;
  }
}


function GenericComponentFactory(ctor) {
  this._ctor = ctor;
}

GenericComponentFactory.prototype = {

  _ctor: null,

  // nsIFactory
  createInstance: function(outer, iid) {
    if (outer != null)
      throw Cr.NS_ERROR_NO_AGGREGATION;
    return (new this._ctor()).QueryInterface(iid);
  },

  // nsISupports
  QueryInterface: function(iid) {
    if (iid.equals(Ci.nsIFactory) ||
        iid.equals(Ci.nsISupports))
      return this;
    throw Cr.NS_ERROR_NO_INTERFACE;
  },
};

var Module = {
  QueryInterface: function(iid) {
    if (iid.equals(Ci.nsIModule) ||
        iid.equals(Ci.nsISupports))
      return this;

    throw Cr.NS_ERROR_NO_INTERFACE;
  },

  getClassObject: function(cm, cid, iid) {
    if (!iid.equals(Ci.nsIFactory))
      throw Cr.NS_ERROR_NOT_IMPLEMENTED;

    if (cid.equals(SM_CLASSID))
      return new GenericComponentFactory(SearchMigratable)

    throw Cr.NS_ERROR_NO_INTERFACE;
  },

  registerSelf: function(cm, file, location, type) {
    var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
    cr.registerFactoryLocation(SM_CLASSID, SM_CLASSNAME, SM_CONTRACTID,
                               file, location, type);

    var catman = Cc['@mozilla.org/categorymanager;1']
      .getService(Ci.nsICategoryManager);
    catman.addCategoryEntry('flockMigratable', SM_CLASSNAME, SM_CONTRACTID,
                            true, true);
  },

  unregisterSelf: function(cm, location, type) {
    var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
    cr.unregisterFactoryLocation(SM_CLASSID, location);
  },

  canUnload: function(cm) {
    return true;
  },
};

function NSGetModule(compMgr, fileSpec)
{
  return Module;
}
