import { Component, NgZone, OnDestroy, OnInit } from "@angular/core";
import { Router } from "@angular/router";

import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { Utils } from "@bitwarden/common/misc/utils";

import { BrowserApi } from "../../browser/browserApi";

interface ExcludedDomain {
  uri: string;
  showCurrentUris: boolean;
}

const BroadcasterSubscriptionId = "excludedDomains";

@Component({
  selector: "app-excluded-domains",
  templateUrl: "excluded-domains.component.html",
})
export class ExcludedDomainsComponent implements OnInit, OnDestroy {
  excludedDomains: ExcludedDomain[] = [];
  currentUris: string[];
  loadCurrentUrisTimeout: number;

  constructor(
    private stateService: StateService,
    private i18nService: I18nService,
    private router: Router,
    private broadcasterService: BroadcasterService,
    private ngZone: NgZone,
    private platformUtilsService: PlatformUtilsService
  ) {}

  async ngOnInit() {
    const savedDomains = await this.stateService.getNeverDomains();
    if (savedDomains) {
      for (const uri of Object.keys(savedDomains)) {
        this.excludedDomains.push({ uri: uri, showCurrentUris: false });
      }
    }

    await this.loadCurrentUris();

    this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
      this.ngZone.run(async () => {
        switch (message.command) {
          case "tabChanged":
          case "windowChanged":
            if (this.loadCurrentUrisTimeout != null) {
              window.clearTimeout(this.loadCurrentUrisTimeout);
            }
            this.loadCurrentUrisTimeout = window.setTimeout(
              async () => await this.loadCurrentUris(),
              500
            );
            break;
          default:
            break;
        }
      });
    });
  }

  ngOnDestroy() {
    this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
  }

  async addUri() {
    this.excludedDomains.push({ uri: "", showCurrentUris: false });
  }

  async removeUri(i: number) {
    this.excludedDomains.splice(i, 1);
  }

  async submit() {
    const savedDomains: { [name: string]: null } = {};
    for (const domain of this.excludedDomains) {
      if (domain.uri && domain.uri !== "") {
        const validDomain = Utils.getHostname(domain.uri);
        if (!validDomain) {
          this.platformUtilsService.showToast(
            "error",
            null,
            this.i18nService.t("excludedDomainsInvalidDomain", domain.uri)
          );
          return;
        }
        savedDomains[validDomain] = null;
      }
    }
    await this.stateService.setNeverDomains(savedDomains);
    this.router.navigate(["/tabs/settings"]);
  }

  trackByFunction(index: number, item: any) {
    return index;
  }

  toggleUriInput(domain: ExcludedDomain) {
    domain.showCurrentUris = !domain.showCurrentUris;
  }

  async loadCurrentUris() {
    const tabs = await BrowserApi.tabsQuery({ windowType: "normal" });
    if (tabs) {
      const uriSet = new Set(tabs.map((tab) => Utils.getHostname(tab.url)));
      uriSet.delete(null);
      this.currentUris = Array.from(uriSet);
    }
  }
}
