import { UUID } from '@bcase/core';
import { h } from "@stencil/core";
import SortableJS from 'sortablejs';
import { Block } from '../../models/block';
import { NativeEvent } from '../../utils/native-event';
import { storedFiles } from '../../utils/stored-files';
export class BceBlockEditor {
    constructor() {
        this.preview = false;
        this.labels = {};
        this.value = Block.empty();
        this.labelTitle = 'Screen creation';
        this.labelSubtitle = "Use the '+' button below to add elements to the screen.";
        this.handleSort = (event) => {
            const { oldIndex, newIndex } = event;
            const clone = [...this.value.elements];
            clone.splice(newIndex, 0, clone.splice(oldIndex, 1)[0]);
            this.value = Object.assign({}, this.value, { elements: clone });
            this.el.dispatchEvent(new NativeEvent('input'));
        };
        this.handleTemplate = (event) => {
            const element = event.target;
            if (!element)
                return;
            event.cancelBubble = true;
            const index = this.value.elements.findIndex(v => v.id === element.id);
            if (index < 0)
                return;
            const clone = [...this.value.elements];
            clone.splice(index, 1, Object.assign({}, this.value.elements[index], element.template));
            this.value = Object.assign({}, this.value, { elements: clone });
            this.el.dispatchEvent(new NativeEvent('input'));
        };
        this.handleDelete = (event) => {
            const element = event.target;
            if (!element)
                return;
            // Delete stored files
            storedFiles(element.template, false)
                .map(path => ({ id: path.match(/BCE:\/\/([^/]+)\//)[1], path }))
                .forEach(detail => this.fileDelete.emit(detail));
            const elements = this.value.elements.filter(v => v.id !== element.id);
            this.value = Object.assign({}, this.value, { elements });
            this.el.dispatchEvent(new NativeEvent('input'));
        };
        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({}, this.value.elements[index], { id: UUID.v4() }));
            this.value = Object.assign({}, this.value, { elements: clone });
            this.el.dispatchEvent(new NativeEvent('input'));
        };
    }
    async addElement(type) {
        const element = { id: UUID.v4(), type };
        this.value = Object.assign({}, this.value, { elements: [...this.value.elements, element] });
        this.el.dispatchEvent(new NativeEvent('input'));
    }
    async getStoredFiles() {
        return storedFiles(this.value);
    }
    getName(type) {
        const name = this.labels &&
            this.labels.elements &&
            this.labels.elements[type] &&
            this.labels.elements[type].name;
        return name
            ? name
            : Object.entries(Block.Type).find(entry => entry[1] === type)[0];
    }
    componentDidLoad() {
        SortableJS.create(this.el, {
            sort: true,
            handle: 'bce-element > div',
            draggable: 'bce-element',
            onUpdate: this.handleSort
        });
    }
    renderElements() {
        const whitelist = this.whitelist ? this.whitelist.split(',') : [];
        const blacklist = this.blacklist ? this.blacklist.split(',') : [];
        return this.value.elements
            .filter(e => (whitelist.length ? whitelist.indexOf(e.type) >= 0 : true))
            .filter(e => (blacklist.length ? blacklist.indexOf(e.type) < 0 : true))
            .map(e => (h("bce-element", { id: e.id, key: e.id, type: e.type, name: this.getName(e.type), labels: this.labels, template: e, resolveLocation: this.resolveLocation, editor: !this.preview, onTemplate: this.handleTemplate, onDelete: this.handleDelete, onDuplicate: this.handleDuplicate })));
    }
    render() {
        const whitelist = this.whitelist ? this.whitelist.split(',') : [];
        const blacklist = this.blacklist ? this.blacklist.split(',') : [];
        const options = Object.keys(Block.Type)
            .map(key => Block.Type[key])
            .filter(type => (whitelist.length ? whitelist.indexOf(type) >= 0 : true))
            .filter(type => (blacklist.length ? blacklist.indexOf(type) < 0 : true))
            .map(type => (h("bce-button", { icon: Block.ICON_MAP[type], onClick: () => this.addElement(type) }, this.getName(type))));
        return [
            !this.preview && this.labelTitle && h("h5", null, this.labelTitle),
            !this.preview && this.labelSubtitle && h("p", null, this.labelSubtitle),
            h("slot", null),
            this.renderElements(),
            !this.preview && h("bce-element-fab", null, options)
        ];
    }
    static get is() { return "bce-block-editor"; }
    static get originalStyleUrls() { return {
        "$": ["bce-block-editor.scss"]
    }; }
    static get styleUrls() { return {
        "$": ["bce-block-editor.css"]
    }; }
    static get properties() { return {
        "preview": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "preview",
            "reflect": true,
            "defaultValue": "false"
        },
        "labels": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "ElementLabels",
                "resolved": "ElementLabels",
                "references": {
                    "ElementLabels": {
                        "location": "import",
                        "path": "../../models/labels"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "defaultValue": "{}"
        },
        "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
        },
        "blacklist": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string | undefined",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "blacklist",
            "reflect": false
        },
        "resolveLocation": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "ResolveLocation",
                "resolved": "((location: string) => Promise<string>) | undefined",
                "references": {
                    "ResolveLocation": {
                        "location": "import",
                        "path": "../../models/resolve-location"
                    }
                }
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            }
        },
        "labelTitle": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "label-title",
            "reflect": false,
            "defaultValue": "'Screen creation'"
        },
        "labelSubtitle": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "label-subtitle",
            "reflect": false,
            "defaultValue": "\"Use the '+' button below to add elements to the screen.\""
        }
    }; }
    static get events() { return [{
            "method": "fileDelete",
            "name": "file-delete",
            "bubbles": true,
            "cancelable": true,
            "composed": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "complexType": {
                "original": "{ id: string; path: string }",
                "resolved": "{ id: string; path: string; }",
                "references": {}
            }
        }]; }
    static get methods() { return {
        "addElement": {
            "complexType": {
                "signature": "(type: Block.Type) => Promise<void>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    },
                    "Block": {
                        "location": "import",
                        "path": "../../models/block"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "getStoredFiles": {
            "complexType": {
                "signature": "() => Promise<string[]>",
                "parameters": [],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<string[]>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        }
    }; }
    static get elementRef() { return "el"; }
}
