"use strict";
var path = require("path");
var url = require("url");

exports.toFileUrl = function (fileName) {
  // Beyond just the `path.resolve`, this is mostly for the benefit of Windows,
  // where we need to convert "\" to "/" and add an extra "/" prefix before the
  // drive letter.
  var pathname = path.resolve(process.cwd(), fileName).replace(/\\/g, "/");
  if (pathname[0] !== "/") {
    pathname = "/" + pathname;
  }

  return "file://" + pathname;
};

/**
 * Define a setter on an object
 *
 * This method replaces any existing setter but leaves getters in place.
 *
 * - `object` {Object} the object to define the setter on
 * - `property` {String} the name of the setter
 * - `setterFn` {Function} the setter
 */
exports.defineSetter = function defineSetter(object, property, setterFn) {
  var descriptor = Object.getOwnPropertyDescriptor(object, property) || {
    configurable: true,
    enumerable: true
  };

  descriptor.set = setterFn;

  Object.defineProperty(object, property, descriptor);
};

/**
 * Define a getter on an object
 *
 * This method replaces any existing getter but leaves setters in place.
 *
 * - `object` {Object} the object to define the getter on
 * - `property` {String} the name of the getter
 * - `getterFn` {Function} the getter
 */
exports.defineGetter = function defineGetter(object, property, getterFn) {
  var descriptor = Object.getOwnPropertyDescriptor(object, property) || {
    configurable: true,
    enumerable: true
  };

  descriptor.get = getterFn;

  Object.defineProperty(object, property, descriptor);
};

/**
 * Create an object with the given prototype
 *
 * Optionally augment the created object.
 *
 * - `prototype` {Object} the created object's prototype
 * - `[properties]` {Object} properties to attach to the created object
 */
exports.createFrom = function createFrom(prototype, properties) {
  properties = properties || {};

  var descriptors = {};
  Object.getOwnPropertyNames(properties).forEach(function (name) {
    descriptors[name] = Object.getOwnPropertyDescriptor(properties, name);
  });

  return Object.create(prototype, descriptors);
};

/**
 * Create an inheritance relationship between two classes
 *
 * Optionally augment the inherited prototype.
 *
 * - `Superclass` {Function} the inherited class
 * - `Subclass` {Function} the inheriting class
 * - `[properties]` {Object} properties to attach to the inherited prototype
 */
exports.inheritFrom = function inheritFrom(Superclass, Subclass, properties) {
  properties = properties || {};

  Object.defineProperty(properties, "constructor", {
    value: Subclass,
    writable: true,
    configurable: true
  });

  Subclass.prototype = exports.createFrom(Superclass.prototype, properties);
};

/**
 * Define a list of constants on a constructor and its .prototype
 *
 * - `Constructor` {Function} the constructor to define the constants on
 * - `propertyMap` {Object}  key/value map of properties to define
 */
exports.addConstants = function addConstants(Constructor, propertyMap) {
  for (var property in propertyMap) {
    var value = propertyMap[property];
    addConstant(Constructor, property, value);
    addConstant(Constructor.prototype, property, value);
  }
};

function addConstant(object, property, value) {
  Object.defineProperty(object, property, {
    configurable: false,
    enumerable: true,
    value: value,
    writable: false
  });
}

var memoizeQueryTypeCounter = 0;

/**
 * Returns a version of a method that memoizes specific types of calls on the object
 *
 * - `fn` {Function} the method to be memozied
 */
exports.memoizeQuery = function memoizeQuery(fn) {
  // Only memoize query functions with arity <= 2
  if (fn.length > 2) {
    return fn;
  }

  var type = memoizeQueryTypeCounter++;

  return function () {
    if (!this._memoizedQueries) {
      return fn.apply(this, arguments);
    }

    if (!this._memoizedQueries[type]) {
      this._memoizedQueries[type] = Object.create(null);
    }

    var key;
    if (arguments.length === 1 && typeof arguments[0] === "string") {
      key = arguments[0];
    } else if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "string") {
      key = arguments[0] + "::" + arguments[1];
    } else {
      return fn.apply(this, arguments);
    }

    if (!(key in this._memoizedQueries[type])) {
      this._memoizedQueries[type][key] = fn.apply(this, arguments);
    }
    return this._memoizedQueries[type][key];
  };
};

/**
* A slightly-more-compliant version of `url.resolve`, taking care of a few Node bugs.
*/
exports.resolveHref = function resolveHref(baseUrl, href) {
  // If href is "about:blank", Node tries to be too clever.
  if (href === "about:blank") {
    return href;
  }

  if (baseUrl === resolveHref.memoizedUrl && resolveHref.cache && resolveHref.cache[href]) {
    return resolveHref.cache[href];
  }

  // When switching protocols, the path doesn't get canonicalized (i.e. .s and ..s are still left):
  // https://github.com/joyent/node/issues/5453
  var intermediate = url.resolve(baseUrl, href);

  // This canonicalizes the path, at the cost of overwriting the hash.
  var nextStep = url.resolve(intermediate, "#");

  // But it breaks file URLs by removing their colon O_o, so put that back.
  nextStep = nextStep.replace(/^file:\/\/([a-z])\//i, "file:///$1:/");

  // So, insert the hash back in, if there was one.
  var parsed = url.parse(intermediate);
  var fixed = nextStep.slice(0, -1) + (parsed.hash || "");

  // Finally, fix file:/// URLs on Windows, where Node removes their drive letters:
  // https://github.com/joyent/node/issues/5452
  if (/^file\:\/\/\/[a-z]\:\//i.test(baseUrl) && /^file\:\/\/\//.test(fixed) &&
      !/^file\:\/\/\/[a-z]\:\//i.test(fixed)) {
    fixed = fixed.replace(/^file\:\/\/\//, baseUrl.substring(0, 11));
  }

  // HORRIBLE HACK: encode \u00E4 correctly just so that we pass
  // https://github.com/w3c/web-platform-tests/blob/e75f01a689a3481f5c773315c2c2527712cf8c2c/dom/nodes/DOMImplementation-createHTMLDocument.html#L71-L72
  // Eventually we should replace this with a real URL parser based on the URL standard.
  fixed = fixed.replace(/\u00E4/, "%C3%A4");

  if (baseUrl !== resolveHref.memoizedUrl) {
    resolveHref.memoizedUrl = baseUrl;
    resolveHref.cache = {};
  }
  resolveHref.cache[href] = fixed;

  return fixed;
};
