// 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 MM_CONTRACTID = "@flock.com/migration-manager;1";
const MM_CLASSID = Components.ID("{481e822d-937f-4e76-8afc-f636061b7ac6}");
const MM_CLASSNAME = "Flock Migration Manager";


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

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


function MigrationManager() {
  this._logger = CC["@flock.com/logger;1"].createInstance(CI.flockILogger);
  this._logger.init("migrationmanager");
}

MigrationManager.prototype = new FlockXPCOMUtils.genericComponent(
  MM_CLASSNAME,
  MM_CLASSID,
  MM_CONTRACTID,
  MigrationManager,
  CI.nsIClassInfo.SINGLETON,
  [CI.flockIMigrationManager]
);

MigrationManager.prototype.setup =
function MM_setup(oldVersion) {
  this._refreshDetectFiles();

  var args = CC["@mozilla.org/supports-array;1"]
             .createInstance(CI.nsISupportsArray);

  // No old version must mean new profile, so skip everything
  if (!oldVersion) {
    this._logger.info("New profile, not doing any migration checks");
    return args;
  }

  var versionStr = CC["@mozilla.org/supports-cstring;1"]
                   .createInstance(CI.nsISupportsCString);
  versionStr.data = oldVersion;
  args.AppendElement(versionStr);

  var catman = CC["@mozilla.org/categorymanager;1"]
               .getService(CI.nsICategoryManager);

  var entries = catman.enumerateCategory("flockMigratable");
  var migrationCount = 0;
  while (entries.hasMoreElements()) {
    var entry = entries.getNext().QueryInterface(CI.nsISupportsCString);
    if (!entry) {
      continue;
    }

    var contractID = catman.getCategoryEntry("flockMigratable", entry.data);

    try {
      var service = CC[contractID].getService(CI.flockIMigratable);

      this._logger.info("Checking " + service.migrationName
                        + " (" + contractID + ")");
      if (service.needsMigration(oldVersion)) {
        this._logger.info(service.migrationName + " needs migration");
        args.AppendElement(service);
        migrationCount++;
      }
    } catch (ex) {
      this._logger.error("needsMigration failed: " + ex);
    }
  }

  this._logger.info("Found " + migrationCount +" services needing migration");
  return args;
};

MigrationManager.prototype._refreshDetectFiles =
function MM__refreshDetectFiles() {
  // Tell the browser startup code to update us from the web when we can
  var prefs = CC["@mozilla.org/preferences-service;1"]
              .getService(CI.nsIPrefBranch);
  prefs.setBoolPref("flock.webdetective.upgraded", false);

  // Need to get handles to the <app>/res/detect as well as the
  // <profile>/detect directories so that we can copy files from the
  // former to the latter.
  var dirSvc = CC["@mozilla.org/file/directory_service;1"]
               .getService(CI.nsIProperties);

  // Get the file spec for <app>/res/detect
  var appDetectDir = dirSvc.get("ARes", CI.nsIFile);
  appDetectDir.append("detect");

  // Get the file handle for <profile>/detect
  var profDetectDir = dirSvc.get("ProfD", CI.nsIFile);
  profDetectDir.append("detect");

  if (!profDetectDir || !profDetectDir.exists()) {
    return;
  }

  var dirEntries = appDetectDir.directoryEntries;
  while (dirEntries.hasMoreElements()) {
    var file = dirEntries.getNext().QueryInterface(CI.nsIFile);

    if (file.isFile() &&
        file.path.substr(file.path.length - 4).toLowerCase() === ".xml")
    {
      // 'file' now represents a new XML file we want to copy into the
      // user's profile.  But we may need to delete the old version of the
      // file first.
      var oldFile = profDetectDir.clone();
      oldFile.append(file.leafName);

      if (oldFile.exists()) {
        this._logger.debug("removing old " + oldFile.leafName);
        oldFile.remove(false); // Non-recursive
      }

      this._logger.debug("copying " + file.leafName + " to "
                         + profDetectDir.path);
      file.copyTo(profDetectDir, null);
    }
  }
};

var gComponentsArray = [MigrationManager];

var NSGetModule = FlockXPCOMUtils.generateNSGetModule(MM_CLASSNAME,
                                                      gComponentsArray);
