import { Page } from "../types/Page.js";
import { submitUnsealKey, getSealStatus } from "../api.js";
import { setPageContent, setErrorText, changePage } from "../pageUtils.js";
import { makeElement } from "../htmlUtils.js";
import { Margin } from "../elements/Margin.js";
import { MarginInline } from "../elements/MarginInline.js";
import i18next from 'i18next';
import QrScanner from 'qr-scanner';

import qrScannerWorkerSource from '!!raw-loader!qr-scanner/qr-scanner-worker.min.js';
QrScanner.WORKER_PATH = URL.createObjectURL(new Blob([qrScannerWorkerSource]));

const UnsealInputModes = {
  FORM_INPUT: "FORM_INPUT",
  QR_INPUT: "QR_INPUT"
}

export class UnsealPage extends Page {
  constructor() {
    super();
    //this.mode = UnsealInputModes.QR_INPUT;
    this.mode = UnsealInputModes.FORM_INPUT;
  }
  cleanup() {
    this.deinitWebcam()
    clearInterval(this.refresher);
  }

  deinitWebcam() {
    try {
      this.stream.getTracks().forEach(function (track) {
        track.stop();
      });
    } catch {

    }

  }

  makeRefresher() {
    this.refresher = setInterval(async function () {
      this.updateSealProgress(await getSealStatus());
    }.bind(this), 1000);
  }

  async render() {
    this.unsealProgress = makeElement({
      tag: "progress",
      class: "uk-progress",
      attributes: { value: "0", max: "0" }
    });
    this.unsealProgressText = makeElement({
      tag: "p",
      text: i18next.t("unseal_keys_progress", { progress: "0", keys_needed: "0" }),
    });
    this.unsealInputContent = makeElement({
      tag: "div"
    })
    setPageContent(makeElement({
      tag: "div",
      children: [
        this.unsealProgress,
        makeElement({
          tag: "p",
          id: "errorText",
          class: ["uk-text-danger", "uk-margin-top"]
        }),
        this.unsealProgressText,
        this.unsealInputContent
      ]
    }));
    this.switchInputMode(this.mode);
    this.updateSealProgress(await getSealStatus());
    this.makeRefresher();
  }

  setButtons(method) {
    let newMethod;
    let buttonText;
    newMethod = method == UnsealInputModes.FORM_INPUT ? UnsealInputModes.QR_INPUT : UnsealInputModes.FORM_INPUT;
    buttonText = newMethod == UnsealInputModes.FORM_INPUT ? i18next.t("unseal_input_btn") : i18next.t("unseal_qr_btn");
    this.unsealInputContent.appendChild(makeElement({
      tag: "button",
      class: ["uk-button", "uk-button-primary"],
      text: buttonText,
      onclick: () => {
        this.switchInputMode(newMethod);
      }
    }))
  }


  switchInputMode(method) {
    this.deinitWebcam();
    this.unsealInputContent.querySelectorAll('*').forEach(n => n.remove())
    if (method == UnsealInputModes.FORM_INPUT) this.makeUnsealForm();
    if (method == UnsealInputModes.QR_INPUT) this.makeQRInput();
    this.setButtons(method);
  }

  makeUnsealForm() {
    this.unsealKeyForm = makeElement({
      tag: "form",
      children: [
        MarginInline(makeElement({
          tag: "input",
          class: ["uk-input", "uk-form-width-medium"],
          attributes: {
            required: true,
            type: "password",
            placeholder: i18next.t("key_input_placeholder"),
            name: "key"
          }
        })),
        MarginInline(makeElement({
          tag: "button",
          class: ["uk-button", "uk-button-primary"],
          text: i18next.t("submit_key_btn")
        })),
      ]
    });
    this.unsealInputContent.appendChild(this.unsealKeyForm);
    this.unsealKeyForm.addEventListener("submit", function (e) {
      e.preventDefault();
      this.handleKeySubmit();
    }.bind(this));
  }

  async makeQRInput() {
    let webcamVideo = makeElement({
      tag: "video"
    })

    let QRInput = makeElement({
      tag: "div",
      children: [
        Margin(webcamVideo),
      ]
    })
    this.unsealInputContent.appendChild(QRInput);


    this.stream = await navigator.mediaDevices.getUserMedia({
      video: {
        facingMode: 'environment',
      },
      audio: false,
    });
    webcamVideo.srcObject = this.stream;
    let lastSeenCode = "";
    const qrScanner = new QrScanner(webcamVideo, function (code) {
      if (lastSeenCode == code) return;
      lastSeenCode = code;
      this.submitKey(code);
      console.log('decoded qr code:', code)
    }.bind(this));
    qrScanner.start();
  }

  updateSealProgress(data) {
    let progress = data.progress;
    let keysNeeded = data.t;
    let text = this.unsealProgressText;
    text.innerText = i18next.t("unseal_keys_progress", {
      progress: String(progress),
      keys_needed: String(keysNeeded)
    });
    let progressBar = this.unsealProgress;
    progressBar.value = progress;
    progressBar.max = keysNeeded;
    if (!data.sealed) {
      progressBar.value = keysNeeded;
      changePage("HOME");
    }
  }

  submitKey(key) {
    submitUnsealKey(key).then(_ => {
      getSealStatus().then(data => {
        this.updateSealProgress(data);
      });
    }).catch(e => {
      setErrorText(e.message);
    });
  }

  async handleKeySubmit() {
    let formData = new FormData(this.unsealKeyForm);

    this.submitKey(formData.get("key"))
  }
  get name() {
    return i18next.t("unseal_vault_text");
  }
}