/* 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/. */

const MONITOR_URL = RPMGetStringPref(
  "browser.contentblocking.report.monitor.url",
  ""
);
const MONITOR_SIGN_IN_URL = RPMGetStringPref(
  "browser.contentblocking.report.monitor.sign_in_url",
  ""
);
const HOW_IT_WORKS_URL_PREF = RPMGetFormatURLPref(
  "browser.contentblocking.report.monitor.how_it_works.url"
);
const MONITOR_PREFERENCES_URL = RPMGetFormatURLPref(
  "browser.contentblocking.report.monitor.preferences_url"
);
const MONITOR_HOME_PAGE_URL = RPMGetFormatURLPref(
  "browser.contentblocking.report.monitor.home_page_url"
);

export default class MonitorClass {
  constructor(doc) {
    this.doc = doc;
  }

  init() {
    // Wait for monitor data and display the card.
    this.getMonitorData();

    let monitorAboutLink = this.doc.getElementById("monitor-link");
    monitorAboutLink.addEventListener("click", () => {
      this.doc.sendTelemetryEvent("clickMtrAboutLink");
    });

    const storedEmailLink = this.doc.getElementById(
      "monitor-stored-emails-link"
    );
    storedEmailLink.href = MONITOR_PREFERENCES_URL;
    storedEmailLink.addEventListener(
      "click",
      this.onClickMonitorButton.bind(this)
    );

    const knownBreachesLink = this.doc.getElementById(
      "monitor-known-breaches-link"
    );
    knownBreachesLink.href = MONITOR_HOME_PAGE_URL;
    knownBreachesLink.addEventListener(
      "click",
      this.onClickMonitorButton.bind(this)
    );

    const exposedPasswordsLink = this.doc.getElementById(
      "monitor-exposed-passwords-link"
    );
    exposedPasswordsLink.href = MONITOR_HOME_PAGE_URL;
    exposedPasswordsLink.addEventListener(
      "click",
      this.onClickMonitorButton.bind(this)
    );
  }

  onClickMonitorButton(evt) {
    RPMSendAsyncMessage("ClearMonitorCache");
    switch (evt.currentTarget.id) {
      case "monitor-partial-breaches-link":
        this.doc.sendTelemetryEvent("clickMtrReportLink", "resolve_breaches");
        break;
      case "monitor-breaches-link":
        if (evt.currentTarget.classList.contains("no-breaches-resolved")) {
          this.doc.sendTelemetryEvent("clickMtrReportLink", "manage_breaches");
        } else {
          this.doc.sendTelemetryEvent("clickMtrReportLink", "view_report");
        }
        break;
      case "monitor-stored-emails-link":
        this.doc.sendTelemetryEvent("clickMtrReportLink", "stored_emails");
        break;
      case "monitor-known-breaches-link": {
        const knownBreaches = this.doc.querySelector(
          "span[data-type='known-breaches']"
        );
        if (knownBreaches.classList.contains("known-resolved-breaches")) {
          this.doc.sendTelemetryEvent(
            "clickMtrReportLink",
            "known_resolved_breaches"
          );
        } else if (
          knownBreaches.classList.contains("known-unresolved-breaches")
        ) {
          this.doc.sendTelemetryEvent(
            "clickMtrReportLink",
            "known_unresolved_breaches"
          );
        }
        break;
      }
      case "monitor-exposed-passwords-link": {
        const exposedPasswords = this.doc.querySelector(
          "span[data-type='exposed-passwords']"
        );
        if (
          exposedPasswords.classList.contains("passwords-exposed-all-breaches")
        ) {
          this.doc.sendTelemetryEvent(
            "clickMtrReportLink",
            "exposed_passwords_all_breaches"
          );
        } else if (
          exposedPasswords.classList.contains(
            "passwords-exposed-unresolved-breaches"
          )
        ) {
          this.doc.sendTelemetryEvent(
            "clickMtrReportLink",
            "exposed_passwords_unresolved_breaches"
          );
        }
        break;
      }
    }
  }

  /**
   * Retrieves the monitor data and displays this data in the card.
   */
  getMonitorData() {
    RPMSendQuery("FetchMonitorData", {}).then(monitorData => {
      // Once data for the user is retrieved, display the monitor card.
      this.buildContent(monitorData);

      // Show the Monitor card.
      const monitorUI = this.doc.querySelector(".card.monitor-card.loading");
      monitorUI.classList.remove("loading");
    });
  }

  buildContent(monitorData) {
    const headerContent = this.doc.querySelector(
      "#monitor-header-content span"
    );
    const monitorCard = this.doc.querySelector(".card.monitor-card");
    if (!monitorData.error) {
      monitorCard.classList.add("has-logins");
      this.doc.l10n.setAttributes(
        headerContent,
        "monitor-header-content-signed-in"
      );
      this.renderContentForUserWithAccount(monitorData);
    } else {
      monitorCard.classList.add("no-logins");
      const signUpForMonitorLink = this.doc.getElementById(
        "sign-up-for-monitor-link"
      );
      signUpForMonitorLink.href = this.buildMonitorUrl(monitorData.userEmail);
      this.doc.l10n.setAttributes(signUpForMonitorLink, "monitor-sign-up-link");
      this.doc.l10n.setAttributes(
        headerContent,
        "monitor-header-content-no-account"
      );
      signUpForMonitorLink.addEventListener("click", () => {
        this.doc.sendTelemetryEvent("clickMtrSignupButton");
      });
    }
  }

  /**
   * Builds the appropriate URL that takes the user to the Monitor website's
   * sign-up/sign-in page.
   *
   * @param {string | null} email
   *        Optional. The email used to direct the user to the Monitor website's OAuth
   *        sign-in flow. If null, then direct user to just the Monitor website.
   *
   * @returns {string} URL to Monitor website.
   */
  buildMonitorUrl(email = null) {
    return email
      ? `${MONITOR_SIGN_IN_URL}${encodeURIComponent(email)}`
      : MONITOR_URL;
  }

  renderContentForUserWithAccount(monitorData) {
    const {
      numBreaches,
      numBreachesResolved,
      passwords,
      passwordsResolved,
      monitoredEmails,
    } = monitorData;
    const monitorCardBody = this.doc.querySelector(
      ".card.monitor-card .card-body"
    );
    monitorCardBody.classList.remove("hidden");

    const howItWorksLink = this.doc.getElementById("monitor-link");
    howItWorksLink.href = HOW_IT_WORKS_URL_PREF;

    const storedEmail = this.doc.querySelector(
      "span[data-type='stored-emails']"
    );
    storedEmail.textContent = monitoredEmails;
    const infoMonitoredAddresses = this.doc.getElementById(
      "info-monitored-addresses"
    );
    this.doc.l10n.setAttributes(
      infoMonitoredAddresses,
      "info-monitored-emails",
      { count: monitoredEmails }
    );

    const knownBreaches = this.doc.querySelector(
      "span[data-type='known-breaches']"
    );
    const exposedPasswords = this.doc.querySelector(
      "span[data-type='exposed-passwords']"
    );

    const infoKnownBreaches = this.doc.getElementById("info-known-breaches");
    const infoExposedPasswords = this.doc.getElementById(
      "info-exposed-passwords"
    );

    const breachesWrapper = this.doc.querySelector(".monitor-breaches-wrapper");
    const partialBreachesWrapper = this.doc.querySelector(
      ".monitor-partial-breaches-wrapper"
    );
    const breachesTitle = this.doc.getElementById("monitor-breaches-title");
    const breachesIcon = this.doc.getElementById("monitor-breaches-icon");
    const breachesDesc = this.doc.getElementById(
      "monitor-breaches-description"
    );
    const breachesLink = this.doc.getElementById("monitor-breaches-link");
    if (numBreaches) {
      if (!numBreachesResolved) {
        partialBreachesWrapper.classList.add("hidden");
        knownBreaches.textContent = numBreaches;
        knownBreaches.classList.add("known-unresolved-breaches");
        knownBreaches.classList.remove("known-resolved-breaches");
        this.doc.l10n.setAttributes(
          infoKnownBreaches,
          "info-known-breaches-found",
          { count: numBreaches }
        );
        exposedPasswords.textContent = passwords;
        exposedPasswords.classList.add("passwords-exposed-all-breaches");
        exposedPasswords.classList.remove(
          "passwords-exposed-unresolved-breaches"
        );
        this.doc.l10n.setAttributes(
          infoExposedPasswords,
          "info-exposed-passwords-found",
          { count: passwords }
        );

        breachesIcon.setAttribute(
          "src",
          "chrome://browser/skin/protections/new-feature.svg"
        );
        this.doc.l10n.setAttributes(
          breachesTitle,
          "monitor-breaches-unresolved-title"
        );
        this.doc.l10n.setAttributes(
          breachesDesc,
          "monitor-breaches-unresolved-description"
        );
        this.doc.l10n.setAttributes(
          breachesLink,
          "monitor-manage-breaches-link"
        );
        breachesLink.classList.add("no-breaches-resolved");
      } else if (numBreaches == numBreachesResolved) {
        partialBreachesWrapper.classList.add("hidden");
        knownBreaches.textContent = numBreachesResolved;
        knownBreaches.classList.remove("known-unresolved-breaches");
        knownBreaches.classList.add("known-resolved-breaches");
        this.doc.l10n.setAttributes(
          infoKnownBreaches,
          "info-known-breaches-resolved",
          { count: numBreachesResolved }
        );
        let unresolvedPasswords = passwords - passwordsResolved;
        exposedPasswords.textContent = unresolvedPasswords;
        exposedPasswords.classList.remove("passwords-exposed-all-breaches");
        exposedPasswords.classList.add("passwords-exposed-unresolved-breaches");
        this.doc.l10n.setAttributes(
          infoExposedPasswords,
          "info-exposed-passwords-resolved",
          { count: unresolvedPasswords }
        );

        breachesIcon.setAttribute(
          "src",
          "chrome://browser/skin/protections/resolved-breach.svg"
        );
        this.doc.l10n.setAttributes(
          breachesTitle,
          "monitor-breaches-resolved-title"
        );
        this.doc.l10n.setAttributes(
          breachesDesc,
          "monitor-breaches-resolved-description"
        );
        this.doc.l10n.setAttributes(breachesLink, "monitor-view-report-link");
      } else {
        breachesWrapper.classList.add("hidden");
        knownBreaches.textContent = numBreachesResolved;
        knownBreaches.classList.remove("known-unresolved-breaches");
        knownBreaches.classList.add("known-resolved-breaches");
        this.doc.l10n.setAttributes(
          infoKnownBreaches,
          "info-known-breaches-resolved",
          { count: numBreachesResolved }
        );
        let unresolvedPasswords = passwords - passwordsResolved;
        exposedPasswords.textContent = unresolvedPasswords;
        exposedPasswords.classList.remove("passwords-exposed-all-breaches");
        exposedPasswords.classList.add("passwords-exposed-unresolved-breaches");
        this.doc.l10n.setAttributes(
          infoExposedPasswords,
          "info-exposed-passwords-resolved",
          { count: unresolvedPasswords }
        );

        const partialBreachesTitle = document.getElementById(
          "monitor-partial-breaches-title"
        );
        this.doc.l10n.setAttributes(
          partialBreachesTitle,
          "monitor-partial-breaches-title",
          {
            numBreaches,
            numBreachesResolved,
          }
        );

        const progressBar = this.doc.querySelector(".progress-bar");
        const partialBreachesMotivationTitle = document.getElementById(
          "monitor-partial-breaches-motivation-title"
        );

        let percentageResolved = Math.floor(
          (numBreachesResolved / numBreaches) * 100
        );
        progressBar.setAttribute("value", 100 - percentageResolved);
        switch (true) {
          case percentageResolved > 0 && percentageResolved < 25:
            this.doc.l10n.setAttributes(
              partialBreachesMotivationTitle,
              "monitor-partial-breaches-motivation-title-start"
            );
            break;

          case percentageResolved >= 25 && percentageResolved < 75:
            this.doc.l10n.setAttributes(
              partialBreachesMotivationTitle,
              "monitor-partial-breaches-motivation-title-middle"
            );
            break;

          case percentageResolved >= 75 && percentageResolved < 100:
            this.doc.l10n.setAttributes(
              partialBreachesMotivationTitle,
              "monitor-partial-breaches-motivation-title-end"
            );
            break;
        }

        const partialBreachesPercentage = document.getElementById(
          "monitor-partial-breaches-percentage"
        );
        this.doc.l10n.setAttributes(
          partialBreachesPercentage,
          "monitor-partial-breaches-percentage",
          { percentageResolved }
        );

        const partialBreachesLink = document.getElementById(
          "monitor-partial-breaches-link"
        );
        partialBreachesLink.setAttribute("href", MONITOR_HOME_PAGE_URL);
        partialBreachesLink.addEventListener(
          "click",
          this.onClickMonitorButton.bind(this)
        );
      }
    } else {
      partialBreachesWrapper.classList.add("hidden");
      knownBreaches.textContent = numBreaches;
      knownBreaches.classList.add("known-unresolved-breaches");
      knownBreaches.classList.remove("known-resolved-breaches");
      this.doc.l10n.setAttributes(
        infoKnownBreaches,
        "info-known-breaches-found",
        { count: numBreaches }
      );
      exposedPasswords.textContent = passwords;
      exposedPasswords.classList.add("passwords-exposed-all-breaches");
      exposedPasswords.classList.remove(
        "passwords-exposed-unresolved-breaches"
      );
      this.doc.l10n.setAttributes(
        infoExposedPasswords,
        "info-exposed-passwords-found",
        { count: passwords }
      );

      breachesIcon.setAttribute(
        "src",
        "chrome://browser/skin/protections/resolved-breach.svg"
      );
      this.doc.l10n.setAttributes(breachesTitle, "monitor-no-breaches-title");
      this.doc.l10n.setAttributes(
        breachesDesc,
        "monitor-no-breaches-description"
      );
      this.doc.l10n.setAttributes(breachesLink, "monitor-view-report-link");
    }

    breachesLink.setAttribute("href", MONITOR_HOME_PAGE_URL);
    breachesLink.addEventListener(
      "click",
      this.onClickMonitorButton.bind(this)
    );
  }
}
