“use strict”; const usm = require(“./url-state-machine”);

exports.implementation = class URLImpl {

constructor(constructorArgs) {
  const url = constructorArgs[0];
  const base = constructorArgs[1];

  let parsedBase = null;
  if (base !== undefined) {
    parsedBase = usm.basicURLParse(base);
    if (parsedBase === "failure") {
      throw new TypeError("Invalid base URL");
    }
  }

  const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase });
  if (parsedURL === "failure") {
    throw new TypeError("Invalid URL");
  }

  this._url = parsedURL;

  // TODO: query stuff
}

get href() {
  return usm.serializeURL(this._url);
}

set href(v) {
  const parsedURL = usm.basicURLParse(v);
  if (parsedURL === "failure") {
    throw new TypeError("Invalid URL");
  }

  this._url = parsedURL;
}

get origin() {
  return usm.serializeURLToUnicodeOrigin(this._url);
}

get protocol() {
  return this._url.scheme + ":";
}

set protocol(v) {
  usm.basicURLParse(v + ":", { url: this._url, stateOverride: "scheme start" });
}

get username() {
  return this._url.username;
}

set username(v) {
  if (usm.cannotHaveAUsernamePasswordPort(this._url)) {
    return;
  }

  usm.setTheUsername(this._url, v);
}

get password() {
  return this._url.password;
}

set password(v) {
  if (usm.cannotHaveAUsernamePasswordPort(this._url)) {
    return;
  }

  usm.setThePassword(this._url, v);
}

get host() {
  const url = this._url;

  if (url.host === null) {
    return "";
  }

  if (url.port === null) {
    return usm.serializeHost(url.host);
  }

  return usm.serializeHost(url.host) + ":" + usm.serializeInteger(url.port);
}

set host(v) {
  if (this._url.cannotBeABaseURL) {
    return;
  }

  usm.basicURLParse(v, { url: this._url, stateOverride: "host" });
}

get hostname() {
  if (this._url.host === null) {
    return "";
  }

  return usm.serializeHost(this._url.host);
}

set hostname(v) {
  if (this._url.cannotBeABaseURL) {
    return;
  }

  usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" });
}

get port() {
  if (this._url.port === null) {
    return "";
  }

  return usm.serializeInteger(this._url.port);
}

set port(v) {
  if (usm.cannotHaveAUsernamePasswordPort(this._url)) {
    return;
  }

  if (v === "") {
    this._url.port = null;
  } else {
    usm.basicURLParse(v, { url: this._url, stateOverride: "port" });
  }
}

get pathname() {
  if (this._url.cannotBeABaseURL) {
    return this._url.path[0];
  }

  if (this._url.path.length === 0) {
    return "";
  }

  return "/" + this._url.path.join("/");
}

set pathname(v) {
  if (this._url.cannotBeABaseURL) {
    return;
  }

  this._url.path = [];
  usm.basicURLParse(v, { url: this._url, stateOverride: "path start" });
}

get search() {
  if (this._url.query === null || this._url.query === "") {
    return "";
  }

  return "?" + this._url.query;
}

set search(v) {
  // TODO: query stuff

  const url = this._url;

  if (v === "") {
    url.query = null;
    return;
  }

  const input = v[0] === "?" ? v.substring(1) : v;
  url.query = "";
  usm.basicURLParse(input, { url, stateOverride: "query" });
}

get hash() {
  if (this._url.fragment === null || this._url.fragment === "") {
    return "";
  }

  return "#" + this._url.fragment;
}

set hash(v) {
  if (v === "") {
    this._url.fragment = null;
    return;
  }

  const input = v[0] === "#" ? v.substring(1) : v;
  this._url.fragment = "";
  usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" });
}

toJSON() {
  return this.href;
}

};