/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import {
  html,
  ifDefined,
  repeat,
  when,
} from "chrome://global/content/vendor/lit.all.mjs";
import { escapeHtmlEntities, isSearchEnabled } from "./helpers.mjs";
import { ViewPage } from "./viewpage.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/migration/migration-wizard.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
  BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
  FirefoxViewPlacesQuery:
    "resource:///modules/firefox-view-places-query.sys.mjs",
  PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
  ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs",
});
let XPCOMUtils = ChromeUtils.importESModule(
  "resource://gre/modules/XPCOMUtils.sys.mjs"
).XPCOMUtils;
XPCOMUtils.defineLazyPreferenceGetter(
  lazy,
  "maxRowsPref",
  "browser.firefox-view.max-history-rows",
  -1
);
const NEVER_REMEMBER_HISTORY_PREF = "browser.privatebrowsing.autostart";
const HAS_IMPORTED_HISTORY_PREF = "browser.migrate.interactions.history";
const IMPORT_HISTORY_DISMISSED_PREF =
  "browser.tabs.firefox-view.importHistory.dismissed";
const SEARCH_RESULTS_LIMIT = 300;
class HistoryInView extends ViewPage {
  constructor() {
    super();
    this._started = false;
    this.allHistoryItems = new Map();
    this.historyMapByDate = [];
    this.historyMapBySite = [];
    // Setting maxTabsLength to -1 for no max
    this.maxTabsLength = -1;
    this.placesQuery = new lazy.FirefoxViewPlacesQuery();
    this.searchQuery = "";
    this.searchResults = null;
    this.sortOption = "date";
    this.profileAge = 8;
    this.fullyUpdated = false;
  }
  start() {
    if (this._started) {
      return;
    }
    this._started = true;
    this.#updateAllHistoryItems();
    this.placesQuery.observeHistory(data => this.#updateAllHistoryItems(data));
    this.toggleVisibilityInCardContainer();
  }
  async connectedCallback() {
    super.connectedCallback();
    await this.updateHistoryData();
    XPCOMUtils.defineLazyPreferenceGetter(
      this,
      "importHistoryDismissedPref",
      IMPORT_HISTORY_DISMISSED_PREF,
      false,
      () => {
        this.requestUpdate();
      }
    );
    XPCOMUtils.defineLazyPreferenceGetter(
      this,
      "hasImportedHistoryPref",
      HAS_IMPORTED_HISTORY_PREF,
      false,
      () => {
        this.requestUpdate();
      }
    );
    if (!this.importHistoryDismissedPref && !this.hasImportedHistoryPrefs) {
      let profileAccessor = await lazy.ProfileAge();
      let profileCreateTime = await profileAccessor.created;
      let timeNow = new Date().getTime();
      let profileAge = timeNow - profileCreateTime;
      // Convert milliseconds to days
      this.profileAge = profileAge / 1000 / 60 / 60 / 24;
    }
  }
  stop() {
    if (!this._started) {
      return;
    }
    this._started = false;
    this.placesQuery.close();
    this.toggleVisibilityInCardContainer();
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.stop();
    this.migrationWizardDialog?.removeEventListener(
      "MigrationWizard:Close",
      this.migrationWizardDialog
    );
  }
  async #updateAllHistoryItems(allHistoryItems) {
    if (allHistoryItems) {
      this.allHistoryItems = allHistoryItems;
    } else {
      await this.updateHistoryData();
    }
    this.resetHistoryMaps();
    this.lists.forEach(list => list.requestUpdate());
    await this.#updateSearchResults();
  }
  async #updateSearchResults() {
    if (this.searchQuery) {
      try {
        this.searchResults = await this.placesQuery.searchHistory(
          this.searchQuery,
          SEARCH_RESULTS_LIMIT
        );
      } catch (e) {
        // Connection interrupted, ignore.
      }
    } else {
      this.searchResults = null;
    }
  }
  viewVisibleCallback() {
    this.start();
  }
  viewHiddenCallback() {
    this.stop();
  }
  static queries = {
    cards: { all: "card-container:not([hidden])" },
    migrationWizardDialog: "#migrationWizardDialog",
    emptyState: "fxview-empty-state",
    lists: { all: "fxview-tab-list" },
    showAllHistoryBtn: ".show-all-history-button",
    searchTextbox: "fxview-search-textbox",
    sortInputs: { all: "input[name=history-sort-option]" },
    panelList: "panel-list",
  };
  static properties = {
    ...ViewPage.properties,
    allHistoryItems: { type: Map },
    historyMapByDate: { type: Array },
    historyMapBySite: { type: Array },
    // Making profileAge a reactive property for testing
    profileAge: { type: Number },
    searchResults: { type: Array },
    sortOption: { type: String },
  };
  async getUpdateComplete() {
    await super.getUpdateComplete();
    await Promise.all(Array.from(this.cards).map(card => card.updateComplete));
  }
  async updateHistoryData() {
    this.allHistoryItems = await this.placesQuery.getHistory({
      daysOld: 60,
      limit: lazy.maxRowsPref,
      sortBy: this.sortOption,
    });
  }
  resetHistoryMaps() {
    this.historyMapByDate = [];
    this.historyMapBySite = [];
  }
  createHistoryMaps() {
    if (this.sortOption === "date" && !this.historyMapByDate.length) {
      const {
        visitsFromToday,
        visitsFromYesterday,
        visitsByDay,
        visitsByMonth,
      } = this.placesQuery;
      // Add visits from today and yesterday.
      if (visitsFromToday.length) {
        this.historyMapByDate.push({
          l10nId: "firefoxview-history-date-today",
          items: visitsFromToday,
        });
      }
      if (visitsFromYesterday.length) {
        this.historyMapByDate.push({
          l10nId: "firefoxview-history-date-yesterday",
          items: visitsFromYesterday,
        });
      }
      // Add visits from this month, grouped by day.
      visitsByDay.forEach(visits => {
        this.historyMapByDate.push({
          l10nId: "firefoxview-history-date-this-month",
          items: visits,
        });
      });
      // Add visits from previous months, grouped by month.
      visitsByMonth.forEach(visits => {
        this.historyMapByDate.push({
          l10nId: "firefoxview-history-date-prev-month",
          items: visits,
        });
      });
    } else if (this.sortOption === "site" && !this.historyMapBySite.length) {
      this.historyMapBySite = Array.from(
        this.allHistoryItems.entries(),
        ([domain, items]) => ({
          domain,
          items,
          l10nId: domain ? null : "firefoxview-history-site-localhost",
        })
      ).sort((a, b) => a.domain.localeCompare(b.domain));
    }
  }
  onPrimaryAction(e) {
    // Record telemetry
    Services.telemetry.recordEvent(
      "firefoxview_next",
      "history",
      "visits",
      null,
      {}
    );
    let currentWindow = this.getWindow();
    if (currentWindow.openTrustedLinkIn) {
      let where = lazy.BrowserUtils.whereToOpenLink(
        e.detail.originalEvent,
        false,
        true
      );
      if (where == "current") {
        where = "tab";
      }
      currentWindow.openTrustedLinkIn(e.originalTarget.url, where);
    }
  }
  onSecondaryAction(e) {
    this.triggerNode = e.originalTarget;
    e.target.querySelector("panel-list").toggle(e.detail.originalEvent);
  }
  deleteFromHistory(e) {
    lazy.PlacesUtils.history.remove(this.triggerNode.url);
    this.recordContextMenuTelemetry("delete-from-history", e);
  }
  async onChangeSortOption(e) {
    this.sortOption = e.target.value;
    Services.telemetry.recordEvent(
      "firefoxview_next",
      "sort_history",
      "tabs",
      null,
      {
        sort_type: this.sortOption,
      }
    );
    await this.updateHistoryData();
    await this.#updateSearchResults();
  }
  showAllHistory() {
    // Record telemetry
    Services.telemetry.recordEvent(
      "firefoxview_next",
      "show_all_history",
      "tabs",
      null,
      {}
    );
    // Open History view in Library window
    this.getWindow().PlacesCommandHook.showPlacesOrganizer("History");
  }
  async openMigrationWizard() {
    let migrationWizardDialog = this.migrationWizardDialog;
    if (migrationWizardDialog.open) {
      return;
    }
    await customElements.whenDefined("migration-wizard");
    // If we've been opened before, remove the old wizard and insert a
    // new one to put it back into its starting state.
    if (!migrationWizardDialog.firstElementChild) {
      let wizard = document.createElement("migration-wizard");
      wizard.toggleAttribute("dialog-mode", true);
      migrationWizardDialog.appendChild(wizard);
    }
    migrationWizardDialog.firstElementChild.requestState();
    this.migrationWizardDialog.addEventListener(
      "MigrationWizard:Close",
      function (e) {
        e.currentTarget.close();
      }
    );
    migrationWizardDialog.showModal();
  }
  shouldShowImportBanner() {
    return (
      this.profileAge < 8 &&
      !this.hasImportedHistoryPref &&
      !this.importHistoryDismissedPref
    );
  }
  dismissImportHistory() {
    Services.prefs.setBoolPref(IMPORT_HISTORY_DISMISSED_PREF, true);
  }
  updated() {
    this.fullyUpdated = true;
    if (this.lists?.length) {
      this.toggleVisibilityInCardContainer();
    }
  }
  panelListTemplate() {
    return html`
      
        
        
            ${cardItem.domain}