// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2008
// 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 DOCSHELL_BRIDGE_CLASSNAME = "Flock DocShell Bridge";
const DOCSHELL_BRIDGE_CLASSID =
  Components.ID("{cc0d0ac6-a534-42e2-8c9c-08bd97c8ff8b}");
const DOCSHELL_BRIDGE_CONTRACTID = "@flock.com/docshell-bridge;1";

const PREF_FLOCK_KEYWORD_PROVIDER = "flock.keyword.provider";

const PREF_PHOTO_SAFESEARCH = "flock.photo.safeSearch";

const DNS_NOT_FOUND_REDIRECT_URL = "http://nxdomain.flock.com/index.php";

const SEARCH_TERMS_PLACEHOLDER = "rideaduckwhenyousearch";

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

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


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

  this._ios = CC["@mozilla.org/network/io-service;1"]
              .getService(CI.nsIIOService);
  this._ss = CC["@mozilla.org/browser/search-service;1"]
             .getService(CI.nsIBrowserSearchService);
  this._metrics = CC["@flock.com/metrics-service;1"]
                  .getService(CI.flockIMetricsService);

  this._errorPageEngine = null;
}

DocShellBridge.prototype = new FlockXPCOMUtils.genericComponent(
  DOCSHELL_BRIDGE_CLASSNAME,
  DOCSHELL_BRIDGE_CLASSID,
  DOCSHELL_BRIDGE_CONTRACTID,
  DocShellBridge,
  CI.nsIClassInfo.SINGLETON,
  [CI.flockIDocShellBridge]
);

DocShellBridge.prototype.getURLFromKeywordProvider =
function DB_getURLFromKeywordProvider(aKeyword) {
  var provider, uri;

  provider = FlockPrefsUtils.getLocalizedPref(PREF_FLOCK_KEYWORD_PROVIDER, "");

  var engine = this._ss.getEngineByName(provider);
  if (engine) {
    engine.QueryInterface(CI.flockISearchEngine);
    uri = engine.getSubmissionByContext(aKeyword, null, "u").uri;
  } else {
    // No engine match, assume it's a URL fragment
    uri = this._mangleKeywordIntoURI(aKeyword, provider);
  }

  this._logger.debug("Keyword Search: keyword = '" + aKeyword
                     + "' resulting url = '" + uri.spec + "'");

  this._metrics.report("URLBar-Search", uri.host);

  return uri;
};

DocShellBridge.prototype._getErrorPageEngine =
function DB__getErrorPageEngine() {
  if (!this._errorPageEngine) {
    var sbs = CC["@mozilla.org/intl/stringbundle;1"]
              .getService(CI.nsIStringBundleService);
    var bundle =
      sbs.createBundle("chrome://browser-region/locale/region.properties");

    var engineName = bundle.GetStringFromName("flock.errorpage.enginename");

    var engine = this._ss.getEngineByName(engineName);
    if (!engine) {
      // Invalid engine, fallback to Yahoo!
      engine = this._ss.getEngineByName("Yahoo!");
    }
    engine.QueryInterface(CI.flockISearchEngine);

    this._errorPageEngine = engine;
  }
  return this._errorPageEngine;
};

DocShellBridge.prototype.getErrorPageSearchURL =
function DB_getErrorPageSearchURL(aErrorPage, aErrorType, aURI) {
  var engine = this._getErrorPageEngine();

  // XXX: This search string is a hack, so netError.xhtml knows which bit
  // to substitute the real search terms in
  var submission = engine.getSubmissionByContext(SEARCH_TERMS_PLACEHOLDER,
                                                 null, "e");
  return submission.uri.spec;
};

DocShellBridge.prototype.getDNSNotFoundURL =
function DB_getDNSNotFoundURL(aNotFoundURI) {
  var parts = aNotFoundURI.spec.split("&");
  var url = null;

  // Parse out the bad domain
  for each (var part in parts) {
    if (part.indexOf("u=") == 0) {
      url = part.split("=")[1];
      break;
    }
  }

  if (url) {
    var redirURL = DNS_NOT_FOUND_REDIRECT_URL + "?origURL=" + url;

    // Add safe search parameter
    var safeSearch = FlockPrefsUtils.getBoolPref(PREF_PHOTO_SAFESEARCH);
    redirURL += "&nxdFilter=" + (safeSearch ? "clean" : "any");

    // Add affiliate and type codes
    var engine = this._getErrorPageEngine();
    if (engine) {
      var submission = engine.getSubmissionByContext(SEARCH_TERMS_PLACEHOLDER,
                                                     null, "d");
      var searchURL = submission.uri.spec;

      var parts = searchURL.split("&");

      // Pull out the affiliate and type codes to pass on
      for each (var part in parts) {
        if (part.indexOf("fr=") == 0 || part.indexOf("type=") == 0) {
          redirURL += "&" + part;
        }
      }

      redirURL += "&searchURL=" + encodeURIComponent(searchURL);
    }

    // We have a redirect url
    return redirURL;
  }

  // We don't have a redirect url so redirect to the default net error page
  return null;
};

DocShellBridge.prototype._mangleKeywordIntoURI =
function DB__mangleKeywordIntoURI(aKeyword, aURL) {
  var query = (aKeyword[0] == "?") ? aKeyword.substr(1) : aKeyword;

  // Trim leading/trailing spaces
  query = query.replace(/(^\s+)|(\s+$)/g, "");

  var url = aURL + query;
  return this._ios.newURI(url, null, null);
};

DocShellBridge.prototype.reportErrorPageMetrics =
function DB__reportErrorPageMetrics(aErrorPage, aErrorType) {
  if (aErrorPage == "flockdnsnotfound") {
    this._metrics.report("YahooDMPage-Opened", aErrorType);
  } else {
    this._metrics.report("ErrorPage-Opened", aErrorType);
  }
};

var gComponentsArray = [DocShellBridge];

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