import * as Popper from "@popperjs/core";
import dom from "./dom";

(function (dom) {
  "use strict";
  function hide() {
    dom(".dropdown-menu").each(async function () {
      if (
        dom(this).attr("id") !== undefined &&
        dom('[data-dropdown-replacer="' + dom(this).attr("id") + '"]').length &&
        dom(this).data("dropdown-programmatically") === undefined
      ) {
        let randId = dom(this).attr("id");
        let dropdownToggle = dom('[data-dropdown-replacer="' + randId + '"]')
          .parent()
          .find("[data-tw-toggle='dropdown']");

        dom(this).removeClass("show");
        const event = new Event("hide.tw.dropdown");
        dom(dropdownToggle).parent()[0].dispatchEvent(event);

        await setTimeout(() => {
          dom('[data-dropdown-replacer="' + randId + '"]').replaceWith(this);

          dom(this).removeAttr("style");
          dom(this).removeAttr("data-popper-placement");

          dom(dropdownToggle).attr("aria-expanded", false);

          const event = new Event("hidden.tw.dropdown");
          dom(dropdownToggle).parent()[0].dispatchEvent(event);
        }, 200);
      } else if (
        dom(this).attr("id") !== undefined &&
        !dom('[data-dropdown-replacer="' + dom(this).attr("id") + '"]')
          .length &&
        dom(this).hasClass("show") &&
        dom(this).data("dropdown-programmatically") === undefined
      ) {
        dom(this).remove();
      } else if (dom(this).data("dropdown-programmatically") == "initiate") {
        dom(this).attr("data-dropdown-programmatically", "showed");
      } else if (dom(this).data("dropdown-programmatically") == "showed") {
        dom(this).removeAttr("data-dropdown-programmatically");

        hide();
      }
    });
  }

  function findVisibleDropdownToggle(dropdownToggle) {
    return dropdownToggle.filter((key, dropdownToggle) => {
      return dropdownToggle.offsetParent !== null;
    });
  }

  async function show(dropdown) {
    let dropdownBox = dom(dropdown).find(".dropdown-menu").first();
    let dropdownToggle = findVisibleDropdownToggle(
      dom(dropdown).find("[data-tw-toggle='dropdown']")
    );
    let placement = dom(dropdown).data("tw-placement")
      ? dom(dropdown).data("tw-placement")
      : "bottom-end";
    let randId = "_" + Math.random().toString(36).substr(2, 9);

    hide();

    if (dom(dropdownBox).length) {
      dom(dropdownToggle).attr("aria-expanded", true);

      dom(dropdown).css("position") == "static"
        ? dom(dropdown).css("position", "relative")
        : "";

      dom(dropdownBox).css("width", dom(dropdownBox).css("width").localeCompare("300px") ? "300px": dom(dropdownBox).css("width"));

      dom('<div data-dropdown-replacer="' + randId + '"></div>').insertAfter(
        dropdownBox
      );
      dom(dropdownBox).attr("id", randId).appendTo("body");

      dom(".modal.show").each(function () {
        if (dom(this).find('[data-dropdown-replacer="' + randId + '"]')) {
          dom(dropdownBox).css("z-index", dom(this).css("z-index"));
        }
      });

      Popper.createPopper(dropdownToggle[0], dropdownBox[0], {
        placement: placement,
      });

      dom(dropdownBox).addClass("show");

      const event = new Event("show.tw.dropdown");
      dom(dropdown)[0].dispatchEvent(event);

      await setTimeout(() => {
        const event = new Event("shown.tw.dropdown");
        dom(dropdown)[0].dispatchEvent(event);
      }, 200);
    }
  }

  function toggleProgrammatically(dropdown) {
    let dropdownBox = dom(dropdown).find(".dropdown-menu").first();
    if (dom(dropdownBox).length) {
      showProgrammatically(dropdown);
    } else {
      hide();
    }
  }
  function showProgrammatically(dropdown) {
    if (dom(dropdown).find(".dropdown-menu").length) {
      dom(dropdown)
        .find(".dropdown-menu")
        .attr("data-dropdown-programmatically", "initiate");
    } else {
      let randId = dom("[data-dropdown-replacer]").data("dropdown-replacer");
      dom("#" + randId).attr("data-dropdown-programmatically", "initiate");
    }

    show(dropdown);
  }
  function createInstance(dropdownToggle) {
    const dropdown = dom(dropdownToggle).closest(".dropdown");
    return {
      show() {
        showProgrammatically(dropdown);
      },
      hide() {
        hide();
      },
      toggle() {
        toggleProgrammatically(dropdown);
      },
    };
  }

  dom("body").on("click", function (event) {
    let dropdown = dom(event.target).closest(".dropdown");
    let dropdownToggle = dom(dropdown).find("[data-tw-toggle='dropdown']");
    let dropdownBox = dom(dropdown).find(".dropdown-menu").first();
    let activeDropdownBox = dom(event.target).closest(".dropdown-menu").first();
    let dismissButton = dom(event.target).data("tw-dismiss");

    if (
      (!dom(dropdown).length && !dom(activeDropdownBox).length) ||
      (dom(dropdownToggle).length && !dom(dropdownBox).length) ||
      dismissButton == "dropdown"
    ) {
      hide();
    } else if (!dom(activeDropdownBox).length) {
      show(dropdown);
    }
  });

  document.addEventListener("keydown", function (event) {
    if (event.code == "Escape") {
      hide();
    }
  });

  (function init() {
    dom("[data-tw-toggle='dropdown']").each(function () {
      this["__dropdown"] = createInstance(this);
    });

    if (window.tailwind === undefined) window.tailwind = {};
    window.tailwind.Dropdown = {
      getInstance(el) {
        return el.__dropdown;
      },
      getOrCreateInstance(el) {
        return el.__dropdown === undefined ? createInstance(el) : el.__dropdown;
      },
    };
  })();
})(dom);
