/**
 * Javascript file which handle ChillCollectionType
 *
 * Two events are emitted by this module, both on window and on collection / ul.
 *
 * Collection (an UL element) and entry (a li element) are associated with those
 * events.
 *
 * ```
 * window.addEventListener('collection-add-entry', function(e) {
 *   console.log(e.detail.collection);
 *   console.log(e.detail.entry);
 * });
 *
 * window.addEventListener('collection-remove-entry', function(e) {
 *   console.log(e.detail.collection);
 *   console.log(e.detail.entry);
 * });
 *
 * collection.addEventListener('collection-add-entry', function(e) {
 *   console.log(e.detail.collection);
 *   console.log(e.detail.entry);
 * });
 *
 * collection.addEventListener('collection-remove-entry', function(e) {
 *   console.log(e.detail.collection);
 *   console.log(e.detail.entry);
 * });
 * ```
 */
import "./collection.scss";

declare global {
  interface GlobalEventHandlersEventMap {
    "show-hide-show": CustomEvent<{
      id: number;
      froms: HTMLElement[];
      container: HTMLElement;
    }>;
  }
}

export class CollectionEventPayload {
  collection: HTMLUListElement;
  entry: HTMLLIElement;

  constructor(collection: HTMLUListElement, entry: HTMLLIElement) {
    this.collection = collection;
    this.entry = entry;
  }
}

export const handleAdd = (button: any): void => {
  const form_name = button.dataset.collectionAddTarget,
    prototype = button.dataset.formPrototype,
    collection: HTMLUListElement | null = document.querySelector(
      'ul[data-collection-name="' + form_name + '"]',
    );

  if (collection === null) {
    return;
  }

  const empty_explain: HTMLLIElement | null = collection.querySelector(
      "li[data-collection-empty-explain]",
    ),
    entry = document.createElement("li"),
    counter = collection.querySelectorAll("li.entry").length, // Updated counter logic
    content = prototype.replace(/__name__/g, counter.toString()),
    event = new CustomEvent("collection-add-entry", {
      detail: new CollectionEventPayload(collection, entry),
    });

  console.log(counter);
  console.log(content);

  entry.innerHTML = content;
  entry.classList.add("entry");

  if ("collectionRegular" in collection.dataset) {
    initializeRemove(collection, entry);
    if (empty_explain !== null) {
      empty_explain.remove();
    }
  }

  collection.appendChild(entry);
  collection.dispatchEvent(event);
  window.dispatchEvent(event);
};

const initializeRemove = (
  collection: HTMLUListElement,
  entry: HTMLLIElement,
): void => {
  const button = buildRemoveButton(collection, entry);
  if (null === button) {
    return;
  }
  entry.appendChild(button);
};

export const buildRemoveButton = (
  collection: HTMLUListElement,
  entry: HTMLLIElement,
): HTMLButtonElement | null => {
  const button = document.createElement("button"),
    isPersisted = entry.dataset.collectionIsPersisted || "",
    content = collection.dataset.collectionButtonRemoveLabel || "",
    allowDelete = collection.dataset.collectionAllowDelete || "",
    event = new CustomEvent("collection-remove-entry", {
      detail: new CollectionEventPayload(collection, entry),
    });

  if (allowDelete === "0" && isPersisted === "1") {
    return null;
  }
  button.classList.add("btn", "btn-delete", "remove-entry");
  button.textContent = content;
  button.addEventListener("click", (e: Event) => {
    e.preventDefault();
    entry.remove();
    collection.dispatchEvent(event);
    window.dispatchEvent(event);
  });

  return button;
};

const collectionsInit = new Set<string>();
const buttonsInit = new Set<string>();

const initialize = function (target: Document | Element): void {
  const addButtons: NodeListOf<HTMLButtonElement> = document.querySelectorAll(
      "button[data-collection-add-target]",
    ),
    collections: NodeListOf<HTMLUListElement> = document.querySelectorAll(
      "ul[data-collection-regular]",
    );

  for (let i = 0; i < addButtons.length; i++) {
    const addButton = addButtons[i];
    const uniqid = addButton.dataset.uniqid as string;
    if (buttonsInit.has(uniqid)) {
      continue;
    }
    buttonsInit.add(uniqid);
    addButton.addEventListener("click", (e: Event) => {
      e.preventDefault();
      handleAdd(e.target);
    });
  }
  for (let i = 0; i < collections.length; i++) {
    const collection = collections[i];
    const uniqid = collection.dataset.uniqid as string;
    if (collectionsInit.has(uniqid)) {
      continue;
    }
    collectionsInit.add(uniqid);
    const entries: NodeListOf<HTMLLIElement> =
      collection.querySelectorAll(":scope > li");
    for (let j = 0; j < entries.length; j++) {
      if (entries[j].dataset.collectionEmptyExplain === "1") {
        continue;
      }
      initializeRemove(collections[i], entries[j]);
    }
  }
};

window.addEventListener("DOMContentLoaded", () => {
  initialize(document);
});

window.addEventListener(
  "show-hide-show",
  (
    event: CustomEvent<{
      id: number;
      container: HTMLElement;
      froms: HTMLElement[];
    }>,
  ) => {
    const container = event.detail.container as HTMLElement;
    initialize(container);
  },
);
