'use strict';

var index = require('./index-BEF5cZxd.js');
var string_utils = require('./string.utils-BG4pUfEi.js');
var template = require('./template-Cj6PcLmR.js');
var form = require('./form-GgXzZZ-E.js');
var accessibility = require('./accessibility-BQJmIVWV.js');
var attribute = require('./attribute-CH1-zDDl.js');
require('./sizes-D5zsw2g5.js');
require('./utils-NnC78QR3.js');
require('./constants-DcKnOyW4.js');
require('./colors-DgrrxjsX.js');
require('./constants-CFAhiwqu.js');
require('./constants-357ehBFU.js');

const FormFileClass = {
    root: 'gov-form-file',
    area: 'gov-form-file__area',
    input: 'gov-form-file__input',
    inputFocus: 'gov-form-file__input-focus',
    attachments: 'gov-form-file__attachments',
};

function formatBytes(bytes) {
    const units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
    let l = 0, n = parseInt(bytes, 10) || 0;
    while (n >= 1024 && ++l) {
        n = n / 1024;
    }
    return n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l];
}
function fileAcceptValidation(file, accept) {
    if (typeof accept === 'string' && accept.length) {
        return (accept
            .replace(/\s/g, '')
            .split(',')
            .filter(accept => {
            return new RegExp(accept.replace('*', '.*')).test(file.type);
        }).length > 0);
    }
    else {
        return true;
    }
}
function fileSizeValidation(file, maxSize) {
    const fileSize = Math.round(file.size);
    return fileSize <= maxSize;
}

const GovFormFile = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.govFocus = index.createEvent(this, "gov-focus");
        this.govBlur = index.createEvent(this, "gov-blur");
        this.govFiles = index.createEvent(this, "gov-files");
        this.govAddFile = index.createEvent(this, "gov-add-file");
        this.govRemoveFile = index.createEvent(this, "gov-remove-file");
        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 = string_utils.createID("GovInputFile");
        this.h = template.govHost(this.host);
        this.f = form.govForm(this.h);
    }
    watchControlAttrs() {
        this.passControlAttrs();
    }
    passControlAttrs() {
        this.f.passAttrToControl("invalid", template.toBoolAttr(this.invalid));
        this.f.passAttrToControl("disabled", template.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: string_utils.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 attribute.AttributeObserver(this.host, (attributeName, newValue) => {
            this.onAriaAttributeChange(attributeName, newValue);
        });
        this.attributeObserver.startObserving(attribute.ariaAttributes);
    }
    componentWillLoad() {
        this.f.passAttrToLabel("required", String(this.required));
        this.passControlAttrs();
        this.inheritedAttributes = accessibility.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 (index.h(index.Host, { key: '59bdd8c7d3bf9594fa545146ca44a00f060fccab', class: this.h.classes([FormFileClass.root]), invalid: template.toBoolAttrIfDefined(this.invalid), expanded: template.toBoolAttrIfDefined(this.expanded) }, index.h("div", { key: 'fd1714f4eb7596fdc1eb67fe8b6d25e4ec93f454', class: FormFileClass.area, ref: el => (this.areaRef = el) }, index.h("slot", { key: '2712d87a6889321616b1b4cb03ea0c61aefcd241' }), index.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": template.toBoolAttrIfDefined(this.required), "aria-invalid": template.toBoolAttrIfDefined(this.invalid), "aria-disabled": template.toBoolAttrIfDefined(this.disabled) })), index.h("div", { key: '54a896ed65deef09f11a8b497f926d079fb599d1', class: FormFileClass.inputFocus })), this.h.hasSlot("attachments") ? (index.h("div", { class: FormFileClass.attachments }, index.h("slot", { name: "attachments" }))) : null, this.files.length && this.displayAttachments ? (index.h("div", { class: FormFileClass.attachments }, index.h("gov-attachments", { label: this.accessibleAttachmentsLabel, "accessible-label": this.accessibleAttachmentsLabel }, this.files.map(item => (index.h("gov-attachments-item", { "accessible-remove-labelledby": item.id, "on-gov-remove": () => this.onRemoveFileHandler(item) }, item.file.name, index.h("span", { slot: "name" }, item.file.name), item.acceptValid === false ? (index.h("gov-form-message", { slot: "message", color: "error" }, index.h("gov-icon", { slot: "icon", name: "exclamation-triangle-fill", type: "components" }), item.acceptValid === false ? this.errorAccept : null)) : null, item.sizeValid === false ? (index.h("gov-form-message", { slot: "message", color: "error" }, index.h("gov-icon", { slot: "icon", name: "exclamation-triangle-fill", type: "components" }), this.errorSize.replace("{FILE_SIZE}", formatBytes(this.maxFileSize)))) : null, index.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 = '';
    }
    get host() { return index.getElement(this); }
    static get watchers() { return {
        "disabled": ["watchControlAttrs"],
        "invalid": ["watchControlAttrs"]
    }; }
};

exports.gov_form_file = GovFormFile;
//# sourceMappingURL=gov-form-file.entry.cjs.js.map

//# sourceMappingURL=gov-form-file.cjs.entry.js.map