/* Copyright 2025 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { getUuid } from "pdfjs-lib";

const KEY_STORAGE = "pdfjs.signature";

class SignatureStorage {
  // TODO: Encrypt the data in using a password and add a UI for entering it.
  // We could use the Web Crypto API for this (see https://bradyjoslin.com/blog/encryption-webcrypto/
  // for an example).

  #eventBus;

  #signatures = null;

  #signal = null;

  constructor(eventBus, signal) {
    this.#eventBus = eventBus;
    this.#signal = signal;
  }

  #save() {
    localStorage.setItem(
      KEY_STORAGE,
      JSON.stringify(Object.fromEntries(this.#signatures))
    );
  }

  async getAll() {
    if (this.#signal) {
      window.addEventListener(
        "storage",
        ({ key }) => {
          if (key === KEY_STORAGE) {
            this.#signatures = null;
            this.#eventBus?.dispatch("storedsignatureschanged", {
              source: this,
            });
          }
        },
        { signal: this.#signal }
      );
      this.#signal = null;
    }
    if (!this.#signatures) {
      this.#signatures = new Map();
      const data = localStorage.getItem(KEY_STORAGE);
      if (data) {
        for (const [key, value] of Object.entries(JSON.parse(data))) {
          this.#signatures.set(key, value);
        }
      }
    }
    return this.#signatures;
  }

  async isFull() {
    // Only allow 5 signatures to be saved.
    return (await this.size()) === 5;
  }

  async size() {
    return (await this.getAll()).size;
  }

  async create(data) {
    if (await this.isFull()) {
      return null;
    }
    const uuid = getUuid();
    this.#signatures.set(uuid, data);
    this.#save();

    return uuid;
  }

  async delete(uuid) {
    const signatures = await this.getAll();
    if (!signatures.has(uuid)) {
      return false;
    }
    signatures.delete(uuid);
    this.#save();

    return true;
  }
}

export { SignatureStorage };
