import Template from "./template.js";
import { copyDates as copyBlockDates, copyElement, createManualCopyAction, createManualPasteAction, duplicateBlock, handleBlockPaste, pasteAtPosition, setOrUpdateUuids, } from "./block/clipboard.js";
import { applyBlockDates, checkBlockDates, cleanupBlockDatesCheck, selectBlockDates, } from "./block/dates.js";
import { createBlockAtPosition, moveBlockRelative, removeBlockFromEditor, } from "./block/operations.js";
import { initializeBlockRecursive } from "./block/recursive-init.js";
import { handleOutsideBlockClick, hideBlockHelper, hideBlockUi, manageBlockActions, showBlockHelper, showBlockUi, } from "./block/ui-overlay.js";
import { isLocalhost } from "../services/util.js";
export { pasteFromClipboard, clipboardError } from "./block/clipboard.js";
export default class Block {
    constructor(element, template, editor, code, isCreation) {
        this.init = () => {
            if (!this.template)
                return;
            try {
                this.element.addEventListener("mouseenter", this.onMouseEnter);
                this.element.addEventListener("mouseleave", this.onMouseLeave);
                this.checkDates();
                return initializeBlockRecursive(this, this.template.templates, Boolean(this.isCreation));
            }
            catch {
                if (isLocalhost()) {
                    console.info("[eden] brick not found: " + this.code);
                }
            }
        };
        this.activate = () => {
            this.element.addEventListener("click", this.onClick);
            this.element.addEventListener("paste", this.handlePaste);
            this.observer = new MutationObserver(() => {
                this.contentHasChanged = true;
                this.observer?.disconnect();
            });
            this.observer.observe(this.element, {
                characterData: true,
                attributes: true,
                childList: true,
                subtree: true,
            });
            this.instances?.forEach((instance) => {
                if (typeof instance === "object") {
                    instance.activate();
                }
            });
        };
        this.desactivate = () => {
            this.element.removeEventListener("paste", this.handlePaste);
            this.element.removeEventListener("click", this.onClick);
            this.observer?.disconnect();
            this.hideUi();
            this.instances?.forEach((instance) => instance.desactivate());
        };
        this.cleanRefs = () => {
            this.instances?.forEach((instance) => instance.cleanRefs());
            this.element.removeEventListener("mouseleave", this.onMouseLeave);
            this.element.removeEventListener("mouseenter", this.onMouseEnter);
            this.element.removeEventListener("mousemove", this.onMouseMove);
            delete this.instances;
            delete this.template;
            delete this.editor;
        };
        this.preSave = () => {
            this.cleanupDatesCheck();
            this.instances?.forEach((instance) => {
                if (typeof instance === "object") {
                    instance.preSave();
                }
            });
        };
        this.postSave = () => {
            this.instances?.forEach((instance) => {
                if (typeof instance === "object") {
                    instance.postSave();
                }
            });
            this.checkDates();
        };
        this.displayInfo = async () => {
            const { dates, hidden } = this.element.dataset;
            const { default: EdenInfoUi } = await import("../user-interface/block/eden-info-ui.js");
            this.infoUi = new EdenInfoUi(this.element, dates, hidden);
            this.element.appendChild(this.infoUi);
            if (this.initialPosition !== "relative") {
                this.element.style.position = "relative";
            }
        };
        this.hideInfo = () => {
            if (this.infoUi) {
                this.infoUi.remove();
                delete this.infoUi;
                if (this.initialPosition && this.initialPosition !== "relative") {
                    this.element.style.position = this.initialPosition;
                }
            }
        };
        this.create = (position) => async (code, variant) => {
            await createBlockAtPosition(this, position, code, variant);
        };
        this.createBefore = this.create("beforebegin");
        this.createAfter = this.create("afterend");
        this.remove = () => {
            removeBlockFromEditor(this);
        };
        this.copy = async (elementType, cutMode) => {
            await copyElement(this, elementType, cutMode);
        };
        this.manualCopy = (elementType, cutMode) => createManualCopyAction(this, elementType, cutMode);
        this.copyEditor = this.manualCopy("editor");
        this.copyBlock = this.manualCopy("block");
        this.cutBlock = this.manualCopy("block", true);
        this.copyDates = async () => {
            await copyBlockDates(this);
        };
        this.setOrUpdateUuids = () => {
            setOrUpdateUuids(this);
        };
        this.paste = async (position) => {
            await pasteAtPosition(this, position);
        };
        this.manualPaste = (position) => createManualPasteAction(this, position);
        this.pasteBefore = this.manualPaste("beforebegin");
        this.pasteAfter = this.manualPaste("afterend");
        this.duplicate = async () => {
            await duplicateBlock(this);
        };
        this.selectDates = async () => {
            await selectBlockDates(this);
        };
        this.settings = async () => {
            if (!this.editor)
                return;
            const { default: SettingsModal } = await import("../user-interface/plugin/settings-modal.js");
            new SettingsModal(this.changeSettings, {
                id: this.element.id,
                tags: this.element.dataset.tags || "",
                hidden: this.element.dataset.hidden === "true" || false,
                variant: this.variant,
                tagsLabel: this.editor.tagsLabel,
                allowedTags: this.editor.allowedTags,
                allowMultipleTags: this.editor.allowMultipleTags,
                attributes: this.attributes,
            }, this.template?.variants, this.template?.defaultVariantName).init();
        };
        this.changeSettings = ({ id, tags, variant, hidden, attributes, }) => {
            if (id === "") {
                this.element.removeAttribute("id");
            }
            else {
                this.element.setAttribute("id", id);
            }
            if (tags === "") {
                this.element.removeAttribute("data-tags");
            }
            else {
                this.element.dataset.tags = tags;
            }
            if (!hidden) {
                this.element.removeAttribute("data-hidden");
                this.element.removeAttribute("data-nosnippet");
            }
            else {
                this.element.dataset.hidden = "true";
                this.element.setAttribute("data-nosnippet", "");
            }
            this.updateVariant(variant);
            if (attributes) {
                attributes.forEach(({ property, value }) => {
                    if (value) {
                        this.element.setAttribute(property, value);
                    }
                    else {
                        this.element.removeAttribute(property);
                    }
                });
            }
            this.attributes = this.template?.getAttributes(this.element);
        };
        this.updateVariant = (variant) => {
            if (this.variant) {
                this.element.classList.remove(this.variant);
            }
            if (variant && variant !== "") {
                this.element.classList.add(variant);
            }
            this.variant = this.template?.getVariant(this.element);
            if (this.ui)
                this.ui.variant = this.variant;
        };
        this.changeDates = (dates) => {
            applyBlockDates(this, dates);
        };
        this.move = (position) => () => {
            moveBlockRelative(this, position);
        };
        this.moveBefore = this.move("beforebegin");
        this.moveAfter = this.move("afterend");
        this.showUi = async (e) => {
            await showBlockUi(this, e);
        };
        this.hideUi = () => {
            hideBlockUi(this);
        };
        this.addActions = (actionsGroups) => {
            this.actionsGroups = [...(this.actionsGroups || []), ...actionsGroups];
            this.addToolbars();
        };
        this.addToolbars = () => {
            if (this.ui && this.actionsGroups && this.actionsGroups.length > 0) {
                this.ui.addToolbars(this.actionsGroups);
                this.actionsGroups = [];
            }
        };
        this.removeActions = (actionsGroups) => {
            if (this.ui && actionsGroups && actionsGroups.length > 0) {
                this.ui.removeActions(actionsGroups);
            }
        };
        this.manageActions = async (pluginsToActivate) => {
            await manageBlockActions(this, pluginsToActivate);
        };
        this.onClick = async (e) => {
            await this.showUi(e);
        };
        this.handleOutsideClick = (e) => {
            handleOutsideBlockClick(this, e);
        };
        this.showHelper = async (e) => {
            await showBlockHelper(this, e);
        };
        this.hideHelper = () => {
            hideBlockHelper(this);
        };
        this.onMouseEnter = () => {
            this.element.addEventListener("mousemove", this.onMouseMove);
        };
        this.onMouseLeave = () => {
            this.element.removeEventListener("mousemove", this.onMouseMove);
            this.hideHelper();
        };
        this.onMouseMove = (e) => {
            const currentMode = document.documentElement.getAttribute("data-eden-mode");
            if (currentMode === "info") {
                this.showHelper(e);
            }
            else {
                this.hideHelper();
            }
        };
        this.handlePaste = async (e) => {
            handleBlockPaste(e);
        };
        this.isFirstChild = () => this.editor?.element.firstChild === this.element;
        this.isLastChild = () => this.editor?.element.lastChild === this.element;
        this.checkDates = () => {
            checkBlockDates(this);
        };
        this.cleanupDatesCheck = () => {
            cleanupBlockDatesCheck(this);
        };
        this.element = element;
        if (template) {
            this.template = new Template(template);
            this.variant = this.template.getVariant(this.element);
            this.attributes = this.template.getAttributes(this.element);
        }
        else {
            this.obsolete = true;
        }
        this.editor = editor;
        this.code = code;
        this.isCreation = isCreation;
        this.initialPosition = element.style.position;
        this.helper = undefined;
        this.instances = [];
        this.activePlugins = [];
        this.actionsGroups = [];
    }
}
