“use strict”; const whatwgURL = require(“whatwg-url”); const arrayEqual = require(“array-equal”); const notImplemented = require(“../../browser/not-implemented.js”); const HashChangeEvent = require(“../generated/HashChangeEvent.js”); const PopStateEvent = require(“../generated/PopStateEvent.js”); const idlUtils = require(“../generated/utils”);

exports.traverseHistory = (window, specifiedEntry, flags) => {

// Not spec compliant, just minimal. Lots of missing steps.

if (flags === undefined) {
  flags = {};
}
const nonBlockingEvents = Boolean(flags.nonBlockingEvents);

const document = idlUtils.implForWrapper(window._document);

const currentEntry = window._sessionHistory[window._currentSessionHistoryEntryIndex];

if (currentEntry.title === undefined) {
  currentEntry.title = document.title;
}

document._URL = specifiedEntry.url;

let hashChanged = false;
let oldURL;
let newURL;
if (specifiedEntry.url.fragment !== currentEntry.url.fragment) {
  hashChanged = true;
  oldURL = currentEntry.url;
  newURL = specifiedEntry.url;
}

const state = specifiedEntry.stateObject; // TODO structured clone
document._history._state = state;

const stateChanged = specifiedEntry.document._history._latestEntry !== specifiedEntry;
specifiedEntry.document._history._latestEntry = specifiedEntry;

if (nonBlockingEvents) {
  window.setTimeout(fireEvents, 0);
} else {
  fireEvents();
}

function fireEvents() {
  if (stateChanged) {
    window.dispatchEvent(PopStateEvent.create(["popstate", {
      bubbles: true,
      cancelable: false,
      state
    }]));
  }

  if (hashChanged) {
    window.dispatchEvent(HashChangeEvent.create(["hashchange", {
      bubbles: true,
      cancelable: false,
      oldURL: whatwgURL.serializeURL(oldURL),
      newURL: whatwgURL.serializeURL(newURL)
    }]));
  }
}

window._currentSessionHistoryEntryIndex = window._sessionHistory.indexOf(specifiedEntry);

};

exports.navigate = (window, newURL) => {

// This is NOT a spec-compliant implementation of navigation in any way. It implements a few selective steps that
// are nice for jsdom users, regarding hash changes. We could maybe implement javascript: URLs in the future, but
// the rest is too hard.

const document = idlUtils.implForWrapper(window._document);

const currentURL = document._URL;

if (newURL.scheme !== currentURL.scheme ||
    newURL.username !== currentURL.username ||
    newURL.password !== currentURL.password ||
    newURL.host !== currentURL.host ||
    newURL.port !== currentURL.port ||
    !arrayEqual(newURL.path, currentURL.path) ||
    newURL.query !== currentURL.query ||
    // Omitted per spec: url.fragment !== this._url.fragment ||
    newURL.cannotBeABaseURL !== currentURL.cannotBeABaseURL) {
  notImplemented("navigation (except hash changes)", window);
  return;
}

if (newURL.fragment !== currentURL.fragment) {
  // https://html.spec.whatwg.org/#scroll-to-fragid

  window._sessionHistory.splice(window._currentSessionHistoryEntryIndex + 1, Infinity);

  document._history._clearHistoryTraversalTasks();

  const newEntry = { document, url: newURL };
  window._sessionHistory.push(newEntry);
  exports.traverseHistory(window, newEntry, { nonBlockingEvents: true });
}

};