import { h, Host } from "@stencil/core";
import { createID } from "../../../utils/string.utils";
import { FormFileClass } from "./constants";
import { govHost, toBoolAttr, toBoolAttrIfDefined } from "../../../helpers/Dom/template";
import { fileAcceptValidation, fileSizeValidation, formatBytes } from "../../../utils/file.utils";
import { govForm } from "../../../helpers/Dom/form";
import { inheritAriaAttributes } from "../../../helpers/Accessibility/accessibility";
import { AttributeObserver } from "../../../helpers/Dom/attribute";
import { ariaAttributes } from "../../../helpers/Accessibility/attributes";
export class GovFormFile {
    constructor() {
        this.eventsRegistered = false;
        /**
         * Expands the file input to fill 100% of the container width.
         */
        this.expanded = false;
        /**
         * Set whether the input is required or not. Please note that this is necessary for accessible inputs when the user is required to fill them.
         * When using this property you need to also set “novalidate” attribute to your form element to prevent browser from displaying its own validation errors.
         */
        this.required = false;
        /**
         * Makes the File component disabled.
         * This prevents users from being able to interact with the File, and conveys its inactive state to assistive technologies.
         */
        this.disabled = false;
        /**
         * After selecting the files, the main input element will be reset.
         * The propagation of the event with the selected files will not be affected.
         */
        this.resetAfterPick = false;
        /**
         * Selected files will not be checked for duplicates based on name and size.
         */
        this.ignoreFileDuplicationCheck = false;
        /**
         * Show list of attachments
         */
        this.displayAttachments = true;
        /**
         * Same as original parameter
         * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/multiple
         */
        this.multiple = false;
        /**
         * Maximum embedded file size
         */
        this.maxFileSize = -1;
        /**
         * Error message when the maximum file size is exceeded
         */
        this.errorSize = "Soubor je větší než povolená velikost {FILE_SIZE}";
        /**
         * Insert unsupported file error message
         */
        this.errorAccept = "Soubor tohoto typu není povolen";
        /**
         * Adds accessible label for the list of attachments.
         */
        this.accessibleAttachmentsLabel = "Přílohy";
        this.files = [];
        this.inheritedAttributes = {};
        this.fileId = createID("GovInputFile");
        this.h = govHost(this.host);
        this.f = govForm(this.h);
    }
    watchControlAttrs() {
        this.passControlAttrs();
    }
    passControlAttrs() {
        this.f.passAttrToControl("invalid", toBoolAttr(this.invalid));
        this.f.passAttrToControl("disabled", toBoolAttr(this.disabled));
        this.f.passAttrToControl("type", "File");
    }
    registerListeners() {
        if (this.eventsRegistered) {
            return;
        }
        this.eventsRegistered = true;
        function highlight() {
            this.areaRef.classList.add("highlight");
        }
        function unhighlight() {
            this.areaRef.classList.remove("highlight");
        }
        this.inputRef.addEventListener("change", e => {
            e.preventDefault();
            e.stopPropagation();
            const files = e.target.files;
            if (this.resetAfterPick) {
                if (files.length) {
                    this.validateFiles(files);
                }
            }
            else {
                this.validateFiles(files);
            }
        }, false);
        if (this.expanded) {
            const events = ["dragover", "dragleave"];
            const inEvents = ["dragenter", "dragover", "mouseenter"];
            const outEvents = ["dragleave", "mouseleave"];
            events.map(eventName => this.inputRef.addEventListener(eventName, this.preventDefaults.bind(this), false));
            inEvents.map(eventName => this.inputRef.addEventListener(eventName, highlight.bind(this), false));
            outEvents.forEach(eventName => this.inputRef.addEventListener(eventName, unhighlight.bind(this), false));
        }
    }
    preventDefaults(e) {
        e.preventDefault();
        e.stopPropagation();
    }
    handleDrop(e) {
        const dataTransfer = e.dataTransfer;
        this.validateFiles(dataTransfer.files);
    }
    validateFiles(files) {
        let filesBuffer = [];
        Array.from(files).map(file => {
            const isFile = this.files.find(item => item.file.name === file.name && item.file.size === file.size) || null;
            if (isFile === null || this.ignoreFileDuplicationCheck) {
                const isSizeValid = typeof this.maxFileSize === "number" && this.maxFileSize > 0 ? fileSizeValidation(file, this.maxFileSize) : true;
                const isAcceptValid = fileAcceptValidation(file, this.accept);
                const newFile = {
                    id: createID("GovFormFile"),
                    file,
                    acceptValid: isAcceptValid,
                    sizeValid: isSizeValid,
                };
                if (this.displayAttachments) {
                    this.files = [...this.files, newFile];
                }
                else {
                    filesBuffer = [...filesBuffer, newFile];
                }
                this.govAddFile.emit({
                    component: FormFileClass.root,
                    file: newFile,
                });
            }
        });
        this.govFiles.emit({
            component: FormFileClass.root,
            files: filesBuffer.length ? filesBuffer : this.files,
        });
        if (this.resetAfterPick) {
            this.reset().finally();
        }
    }
    componentDidLoad() {
        this.attributeObserver = new AttributeObserver(this.host, (attributeName, newValue) => {
            this.onAriaAttributeChange(attributeName, newValue);
        });
        this.attributeObserver.startObserving(ariaAttributes);
    }
    componentWillLoad() {
        this.f.passAttrToLabel("required", String(this.required));
        this.passControlAttrs();
        this.inheritedAttributes = inheritAriaAttributes(this.host);
    }
    async componentDidRender() {
        this.registerListeners();
    }
    disconnectedCallback() {
        var _a;
        (_a = this.attributeObserver) === null || _a === void 0 ? void 0 : _a.stopObserving();
    }
    onAriaAttributeChange(attributeName, newValue) {
        this.host.removeAttribute(attributeName);
        this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { [attributeName]: newValue });
    }
    render() {
        return (h(Host, { key: '59bdd8c7d3bf9594fa545146ca44a00f060fccab', class: this.h.classes([FormFileClass.root]), invalid: toBoolAttrIfDefined(this.invalid), expanded: toBoolAttrIfDefined(this.expanded) }, h("div", { key: 'fd1714f4eb7596fdc1eb67fe8b6d25e4ec93f454', class: FormFileClass.area, ref: el => (this.areaRef = el) }, h("slot", { key: '2712d87a6889321616b1b4cb03ea0c61aefcd241' }), h("input", Object.assign({ key: 'ac998000d9551871016d4c2ab802040634ff6256', class: FormFileClass.input, ref: el => (this.inputRef = el), id: this.identifier || this.fileId, type: "file", name: this.name, accept: this.accept, multiple: this.multiple, onChange: this.onChangeHandler.bind(this), onFocus: this.onFocusHandler.bind(this), onBlur: this.onBlurHandler.bind(this), required: this.required, disabled: this.disabled }, this.inheritedAttributes, { "aria-required": toBoolAttrIfDefined(this.required), "aria-invalid": toBoolAttrIfDefined(this.invalid), "aria-disabled": toBoolAttrIfDefined(this.disabled) })), h("div", { key: '54a896ed65deef09f11a8b497f926d079fb599d1', class: FormFileClass.inputFocus })), this.h.hasSlot("attachments") ? (h("div", { class: FormFileClass.attachments }, h("slot", { name: "attachments" }))) : null, this.files.length && this.displayAttachments ? (h("div", { class: FormFileClass.attachments }, h("gov-attachments", { label: this.accessibleAttachmentsLabel, "accessible-label": this.accessibleAttachmentsLabel }, this.files.map(item => (h("gov-attachments-item", { "accessible-remove-labelledby": item.id, "on-gov-remove": () => this.onRemoveFileHandler(item) }, item.file.name, h("span", { slot: "name" }, item.file.name), item.acceptValid === false ? (h("gov-form-message", { slot: "message", color: "error" }, h("gov-icon", { slot: "icon", name: "exclamation-triangle-fill", type: "components" }), item.acceptValid === false ? this.errorAccept : null)) : null, item.sizeValid === false ? (h("gov-form-message", { slot: "message", color: "error" }, h("gov-icon", { slot: "icon", name: "exclamation-triangle-fill", type: "components" }), this.errorSize.replace("{FILE_SIZE}", formatBytes(this.maxFileSize)))) : null, h("span", { slot: "info" }, "(", formatBytes(item.file.size), ")"))))))) : null));
    }
    onRemoveFileHandler(file) {
        const index = this.files.findIndex(item => item.id === file.id);
        if (index !== -1) {
            const files = this.files;
            const removeFile = this.files[index];
            files.splice(index, 1);
            this.files = [...files];
            this.govRemoveFile.emit({
                component: FormFileClass.root,
                file: removeFile,
            });
            this.govFiles.emit({
                component: FormFileClass.root,
                files,
            });
        }
    }
    onFocusHandler(e) {
        e.stopPropagation();
        this.govFocus.emit({
            component: FormFileClass.root,
            originalEvent: e,
        });
    }
    onBlurHandler(e) {
        e.stopPropagation();
        this.govBlur.emit({
            component: FormFileClass.root,
            originalEvent: e,
        });
    }
    onChangeHandler(e) {
        e.stopPropagation();
    }
    /**
     * Returns the reference of the native element
     */
    async getRef() {
        return this.inputRef;
    }
    /**
     * Returns the reference of the native area element
     */
    async getAreaRef() {
        return this.areaRef;
    }
    /**
     * Remove all files from component state
     */
    async reset() {
        this.files = [];
        this.inputRef.value = '';
    }
    static get is() { return "gov-form-file"; }
    static get properties() {
        return {
            "expanded": {
                "type": "boolean",
                "attribute": "expanded",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Expands the file input to fill 100% of the container width."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "required": {
                "type": "boolean",
                "attribute": "required",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set whether the input is required or not. Please note that this is necessary for accessible inputs when the user is required to fill them.\r\nWhen using this property you need to also set \u201Cnovalidate\u201D attribute to your form element to prevent browser from displaying its own validation errors."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "disabled": {
                "type": "boolean",
                "attribute": "disabled",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Makes the File component disabled.\r\nThis prevents users from being able to interact with the File, and conveys its inactive state to assistive technologies."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "resetAfterPick": {
                "type": "boolean",
                "attribute": "reset-after-pick",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "After selecting the files, the main input element will be reset.\r\nThe propagation of the event with the selected files will not be affected."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "ignoreFileDuplicationCheck": {
                "type": "boolean",
                "attribute": "ignore-file-duplication-check",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Selected files will not be checked for duplicates based on name and size."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "displayAttachments": {
                "type": "boolean",
                "attribute": "display-attachments",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Show list of attachments"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "true"
            },
            "name": {
                "type": "string",
                "attribute": "name",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Name of the input."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "accept": {
                "type": "string",
                "attribute": "accept",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "link",
                            "text": "https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept"
                        }],
                    "text": "Same as original parameter"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "multiple": {
                "type": "boolean",
                "attribute": "multiple",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "link",
                            "text": "https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/multiple"
                        }],
                    "text": "Same as original parameter"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "maxFileSize": {
                "type": "number",
                "attribute": "max-file-size",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Maximum embedded file size"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "-1"
            },
            "identifier": {
                "type": "string",
                "attribute": "identifier",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Custom File identifier."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "invalid": {
                "type": "boolean",
                "attribute": "invalid",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Indicates the entered value does not conform to the format expected by the application."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "errorSize": {
                "type": "string",
                "attribute": "error-size",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Error message when the maximum file size is exceeded"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"Soubor je v\u011Bt\u0161\u00ED ne\u017E povolen\u00E1 velikost {FILE_SIZE}\""
            },
            "errorAccept": {
                "type": "string",
                "attribute": "error-accept",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Insert unsupported file error message"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"Soubor tohoto typu nen\u00ED povolen\""
            },
            "accessibleAttachmentsLabel": {
                "type": "string",
                "attribute": "accessible-attachments-label",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Adds accessible label for the list of attachments."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"P\u0159\u00EDlohy\""
            }
        };
    }
    static get states() {
        return {
            "files": {},
            "inheritedAttributes": {}
        };
    }
    static get events() {
        return [{
                "method": "govFocus",
                "name": "gov-focus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the File has focus."
                },
                "complexType": {
                    "original": "GovFormFileEvent",
                    "resolved": "GovFormFileEvent",
                    "references": {
                        "GovFormFileEvent": {
                            "location": "import",
                            "path": "./gov-form-file.types",
                            "id": "../../../packages/core/src/components/gov-form/file/gov-form-file.types.ts::GovFormFileEvent"
                        }
                    }
                }
            }, {
                "method": "govBlur",
                "name": "gov-blur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the File loses focus."
                },
                "complexType": {
                    "original": "GovFormFileEvent",
                    "resolved": "GovFormFileEvent",
                    "references": {
                        "GovFormFileEvent": {
                            "location": "import",
                            "path": "./gov-form-file.types",
                            "id": "../../../packages/core/src/components/gov-form/file/gov-form-file.types.ts::GovFormFileEvent"
                        }
                    }
                }
            }, {
                "method": "govFiles",
                "name": "gov-files",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Called when the list of inserted files is changed"
                },
                "complexType": {
                    "original": "GovFormFileEvent",
                    "resolved": "GovFormFileEvent",
                    "references": {
                        "GovFormFileEvent": {
                            "location": "import",
                            "path": "./gov-form-file.types",
                            "id": "../../../packages/core/src/components/gov-form/file/gov-form-file.types.ts::GovFormFileEvent"
                        }
                    }
                }
            }, {
                "method": "govAddFile",
                "name": "gov-add-file",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Called when a new file is added"
                },
                "complexType": {
                    "original": "GovFormFileEvent",
                    "resolved": "GovFormFileEvent",
                    "references": {
                        "GovFormFileEvent": {
                            "location": "import",
                            "path": "./gov-form-file.types",
                            "id": "../../../packages/core/src/components/gov-form/file/gov-form-file.types.ts::GovFormFileEvent"
                        }
                    }
                }
            }, {
                "method": "govRemoveFile",
                "name": "gov-remove-file",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Called when a file is removed from the list"
                },
                "complexType": {
                    "original": "GovFormFileEvent",
                    "resolved": "GovFormFileEvent",
                    "references": {
                        "GovFormFileEvent": {
                            "location": "import",
                            "path": "./gov-form-file.types",
                            "id": "../../../packages/core/src/components/gov-form/file/gov-form-file.types.ts::GovFormFileEvent"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "getRef": {
                "complexType": {
                    "signature": "() => Promise<HTMLInputElement>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLInputElement": {
                            "location": "global",
                            "id": "global::HTMLInputElement"
                        }
                    },
                    "return": "Promise<HTMLInputElement>"
                },
                "docs": {
                    "text": "Returns the reference of the native element",
                    "tags": []
                }
            },
            "getAreaRef": {
                "complexType": {
                    "signature": "() => Promise<HTMLDivElement>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLDivElement": {
                            "location": "global",
                            "id": "global::HTMLDivElement"
                        }
                    },
                    "return": "Promise<HTMLDivElement>"
                },
                "docs": {
                    "text": "Returns the reference of the native area element",
                    "tags": []
                }
            },
            "reset": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Remove all files from component state",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "disabled",
                "methodName": "watchControlAttrs"
            }, {
                "propName": "invalid",
                "methodName": "watchControlAttrs"
            }];
    }
}
//# sourceMappingURL=gov-form-file.js.map
