var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return privateMap.get(receiver);
};
var _generateId;
import './bce-element-icons';
import { h } from "@stencil/core";
import SortableJS from 'sortablejs';
import { Block } from '../../models/block';
import { BlockElement } from '../../models/element';
import { storedFiles } from '../../utils/stored-files';
import { getTranslator } from '../../utils/translator';
export class BlockEditor {
    constructor() {
        this.elementAction = [];
        this.elementQuestion = {};
        this.languages = [];
        this.t = getTranslator();
        this.value = Block.empty();
        _generateId.set(this, window.BCE.generateId);
        this.handleEdit = (event) => {
            const element = event.target;
            const index = this.value.elements.findIndex(v => v.id === (element === null || element === void 0 ? void 0 : element.id));
            if (!element || index < 0)
                return;
            const clone = [...this.value.elements];
            const original = this.value.elements[index];
            clone.splice(index, 1, Object.assign(Object.assign({}, original), element.value));
            this.value = Object.assign(Object.assign({}, this.value), { elements: clone });
            event.stopPropagation();
        };
        this.handleSort = (event) => {
            const { oldIndex: from, newIndex: to } = event;
            const clone = [...this.value.elements];
            clone.splice(to, 0, clone.splice(from, 1)[0]);
            this.value = Object.assign(Object.assign({}, this.value), { elements: clone });
            setTimeout(() => {
                const root = this.el.shadowRoot;
                const elements = Array.from(root.querySelectorAll('bce-element-editor'));
                for (const element of elements)
                    element.reattachMenu();
            }, 200);
        };
        this.handleDelete = (event) => {
            const element = event.target;
            if (!element)
                return;
            // Delete stored files
            const files = storedFiles(element.value);
            for (const file of files)
                window.BCE.file.delete(file, {});
            const elements = this.value.elements.filter(v => v.id !== element.id);
            this.value = Object.assign(Object.assign({}, this.value), { elements });
        };
        this.handleDuplicate = (event) => {
            const element = event.target;
            if (!element)
                return;
            const index = this.value.elements.findIndex(v => v.id === element.id);
            const clone = [...this.value.elements];
            clone.splice(index + 1, 0, Object.assign(Object.assign({}, this.value.elements[index]), { id: __classPrivateFieldGet(this, _generateId).call(this) }));
            this.value = Object.assign(Object.assign({}, this.value), { elements: clone });
        };
    }
    watchValue() {
        const event = new Event('input', { bubbles: true, composed: true });
        this.el.dispatchEvent(event);
    }
    async addElement(type) {
        const element = BlockElement.empty(__classPrivateFieldGet(this, _generateId).call(this), type);
        this.value = Object.assign(Object.assign({}, this.value), { elements: [...this.value.elements, element] });
    }
    async getStoredFiles() {
        return storedFiles(this.value);
    }
    async metadata(id, key, value) {
        const index = this.value.elements.findIndex(el => el.id === id);
        if (index < 0)
            throw new Error(`Element ${id} does not exist.`);
        const element = Object.assign(Object.assign({}, this.value.elements[index]), { metadata: Object.assign(Object.assign({}, this.value.elements[index].metadata), { [key]: value }) });
        if (value === undefined)
            delete element.metadata[key];
        const clone = [...this.value.elements];
        clone.splice(index, 1, element);
        this.value = Object.assign(Object.assign({}, this.value), { elements: clone });
        this.el.dispatchEvent(new Event('input'));
    }
    componentDidLoad() {
        const container = this.el.shadowRoot.querySelector('.container');
        SortableJS.create(container, {
            sort: true,
            handle: 'bce-element-editor',
            draggable: 'bce-element-editor',
            onUpdate: this.handleSort
        });
    }
    renderElements() {
        return this.value.elements.map(e => this.preview ? (h("bce-element", { languages: this.languages, language: this._language, template: e, type: e.type })) : (h("bce-element-editor", { elementAction: this.elementAction, elementQuestion: this.elementQuestion[e.type] || [], id: e.id, key: e.id, language: this._language, languages: this.languages, name: this.t(`me-element-${e.type}`), t: this.t, value: e, onDelete: this.handleDelete, onDuplicate: this.handleDuplicate, onInput: this.handleEdit })));
    }
    renderLanguage() {
        const setLanguage = (e) => {
            const target = e.target;
            this._language = target.value;
            e.stopPropagation();
        };
        return (h("bce-select", { type: "dropdown", value: this._language || this.languages[0].key, onInput: setLanguage }, this.languages.map(lang => (h("bce-option", { key: lang.key, value: lang.key }, lang.label)))));
    }
    render() {
        const whitelist = this.whitelist ? this.whitelist.split(/[ ,]/g) : [];
        const blacklist = this.blacklist ? this.blacklist.split(/[ ,]/g) : [];
        const types = BlockElement.TYPES;
        const options = types
            .filter(type => (whitelist.length ? whitelist.indexOf(type) >= 0 : true))
            .filter(type => (blacklist.length ? blacklist.indexOf(type) < 0 : true))
            .map(type => (h("bce-button", { icon: BlockElement.icon(type), onClick: () => this.addElement(type) }, this.t(`me-element-${type}`))));
        const title = this.t('me-block-title');
        const subtitle = this.t('me-block-subtitle');
        return [
            title && h("h5", null, title),
            subtitle && h("p", null, subtitle),
            h("slot", null),
            this.languages.length > 1 && this.renderLanguage(),
            h("div", { class: "container" }, this.renderElements()),
            h("bce-fab", { icon: "fas:plus", inline: true }, options)
        ];
    }
    static get is() { return "bce-block-editor"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() { return {
        "$": ["bce-block-editor.scss"]
    }; }
    static get styleUrls() { return {
        "$": ["bce-block-editor.css"]
    }; }
    static get properties() { return {
        "blacklist": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string | undefined",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "blacklist",
            "reflect": false
        },
        "elementAction": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "ElementAction[]",
                "resolved": "ElementAction[]",
                "references": {
                    "ElementAction": {
                        "location": "import",
                        "path": "../../models/element-action"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "defaultValue": "[]"
        },
        "elementQuestion": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "{\n    [Type in BlockElement.Type]?: ElementQuestion[];\n  }",
                "resolved": "{ icon?: ElementQuestion[] | undefined; image?: ElementQuestion[] | undefined; link?: ElementQuestion[] | undefined; text?: ElementQuestion[] | undefined; audio?: ElementQuestion[] | undefined; checkbox?: ElementQuestion[] | undefined; download?: ElementQuestion[] | undefined; header?: ElementQuestion[] | undefined; input?: ElementQuestion[] | undefined; matrix?: ElementQuestion[] | undefined; radio?: ElementQuestion[] | undefined; slider?: ElementQuestion[] | undefined; sort?: ElementQuestion[] | undefined; table?: ElementQuestion[] | undefined; video?: ElementQuestion[] | undefined; }",
                "references": {
                    "BlockElement": {
                        "location": "import",
                        "path": "../../models/element"
                    },
                    "ElementQuestion": {
                        "location": "import",
                        "path": "../../models/element-question"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "defaultValue": "{}"
        },
        "languages": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "BlockLanguages",
                "resolved": "{ key: string; label: string; }[]",
                "references": {
                    "BlockLanguages": {
                        "location": "import",
                        "path": "../../models/block-languages"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "defaultValue": "[]"
        },
        "preview": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean | undefined",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "preview",
            "reflect": true
        },
        "t": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "I18n.Translator",
                "resolved": "Translator<\"false\" | \"true\" | \"add-item\" | \"answer\" | \"category\" | \"column\" | \"delete-item\" | \"description\" | \"example\" | \"hide-item\" | \"icon\" | \"image\" | \"link\" | \"max\" | \"me-auto-play\" | \"me-block-subtitle\" | \"me-block-title\" | \"me-element-audio\" | \"me-element-checkbox-max\" | \"me-element-checkbox\" | \"me-element-download-placeholder\" | \"me-element-download\" | \"me-element-header-placeholder\" | \"me-element-header\" | \"me-element-icon\" | \"me-element-image\" | \"me-element-input-multiline\" | \"me-element-input\" | \"me-element-link\" | \"me-element-matrix\" | \"me-element-radio\" | \"me-element-slider\" | \"me-element-sort\" | \"me-element-table\" | \"me-element-text\" | \"me-element-video\" | \"me-module-advanced-options\" | \"me-module-graph-subtitle\" | \"me-module-graph-title\" | \"me-module-subtitle\" | \"me-module-title\" | \"me-option\" | \"me-orientation-h\" | \"me-orientation-v\" | \"me-orientation\" | \"me-other\" | \"me-question\" | \"me-required\" | \"min\" | \"name\" | \"row\" | \"show-item\" | \"step-size\" | \"text-left\" | \"text-right\" | \"text\" | \"upload-item\">",
                "references": {
                    "I18n": {
                        "location": "import",
                        "path": "@bce-technology/i18n"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "defaultValue": "getTranslator()"
        },
        "value": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "Block",
                "resolved": "Block",
                "references": {
                    "Block": {
                        "location": "import",
                        "path": "../../models/block"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "defaultValue": "Block.empty()"
        },
        "whitelist": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string | undefined",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "whitelist",
            "reflect": false
        }
    }; }
    static get states() { return {
        "_language": {}
    }; }
    static get methods() { return {
        "addElement": {
            "complexType": {
                "signature": "(type: \"icon\" | \"image\" | \"link\" | \"text\" | \"audio\" | \"checkbox\" | \"download\" | \"header\" | \"input\" | \"matrix\" | \"radio\" | \"slider\" | \"sort\" | \"table\" | \"video\") => Promise<void>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    },
                    "BlockElement": {
                        "location": "import",
                        "path": "../../models/element"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "getStoredFiles": {
            "complexType": {
                "signature": "() => Promise<string[]>",
                "parameters": [],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<string[]>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "metadata": {
            "complexType": {
                "signature": "(id: string, key: string, value?: any) => Promise<void>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }, {
                        "tags": [],
                        "text": ""
                    }, {
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        }
    }; }
    static get elementRef() { return "el"; }
    static get watchers() { return [{
            "propName": "value",
            "methodName": "watchValue"
        }]; }
}
_generateId = new WeakMap();
