var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import * as React from "react";
import { cn, debounce, readableFileSize } from "@utils";
import { ADPIcon } from "../adpIcon";
import { Button } from "../button";
import { StatusCard } from "./statusCard";
import { fileUploadVariants } from "./fileUploadVariants";
export const FileUpload = React.forwardRef((_a, ref) => {
    var { acceptedExtensions, dropAreaCustomMessage, uploadState = null, multiple = true, disabled = false, infoText = null, maxFileSize, retryFailedUpload, resetUploadState, handleUpload, className } = _a, props = __rest(_a, ["acceptedExtensions", "dropAreaCustomMessage", "uploadState", "multiple", "disabled", "infoText", "maxFileSize", "retryFailedUpload", "resetUploadState", "handleUpload", "className"]);
    const hiddenFileInputRef = React.useRef(null);
    const [fileEntries, setFileEntries] = React.useState([]);
    const [dragging, setDragging] = React.useState(false);
    const existingFileNames = fileEntries.map((entry) => entry.file.name);
    const iconTypes = {
        default: "document-upload",
        success: "check-circle-filled",
        error: "times-circle-filled",
        warning: "danger"
    };
    const debouncedSetDragging = React.useMemo(() => debounce((value) => setDragging(value), 100), []);
    const validateFiles = React.useCallback((files) => {
        return files.map((file) => {
            var _a;
            const ext = `.${(_a = file.name.split(".").pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()}`;
            const hasValidExtension = acceptedExtensions.includes(ext);
            const hasValidSize = !maxFileSize || file.size <= maxFileSize;
            if (existingFileNames.includes(file.name)) {
                setFileEntries((prev) => prev.filter((e) => e.file.name !== file.name));
            }
            const state = hasValidExtension && hasValidSize ? "primary" : "warning";
            return { file, state };
        });
    }, [acceptedExtensions, existingFileNames, maxFileSize]);
    const updateFileList = React.useCallback((validated) => {
        setFileEntries((prev) => {
            const list = multiple
                ? [...prev.filter((e) => e.state !== "error"), ...validated]
                : validated;
            return list;
        });
        queueMicrotask(() => {
            const valid = validated.filter((f) => f.state === "primary").map((f) => f.file);
            if (valid.length) {
                handleUpload(multiple ? valid : valid[0]);
            }
        });
    }, [multiple, handleUpload]);
    const handleFileSelection = (e) => {
        const files = Array.from(e.target.files || []);
        updateFileList(validateFiles(files));
        if (hiddenFileInputRef.current) {
            hiddenFileInputRef.current.value = "";
        }
    };
    const handleDrop = (e) => {
        e.preventDefault();
        setDragging(false);
        if (!disabled) {
            let dropped = Array.from(e.dataTransfer.files);
            if (!multiple && dropped.length > 1) {
                dropped = [dropped[0]];
            }
            updateFileList(validateFiles(dropped));
        }
    };
    const variant = React.useMemo(() => {
        if (!fileEntries.length) {
            return "default";
        }
        const stats = fileEntries.reduce((acc, f) => {
            var _a, _b;
            if (f.state === "error" || ((_a = uploadState === null || uploadState === void 0 ? void 0 : uploadState[f.file.name]) === null || _a === void 0 ? void 0 : _a.error)) {
                acc.hasErrors = true;
            }
            if (f.state === "warning") {
                acc.hasWarnings = true;
            }
            if (((_b = uploadState === null || uploadState === void 0 ? void 0 : uploadState[f.file.name]) === null || _b === void 0 ? void 0 : _b.progress) !== 100) {
                acc.allUploaded = false;
            }
            return acc;
        }, { hasErrors: false, hasWarnings: false, allUploaded: true });
        if (stats.hasErrors) {
            return "error";
        }
        if (stats.hasWarnings) {
            return "warning";
        }
        if (stats.allUploaded) {
            return "success";
        }
        return "default";
    }, [fileEntries, uploadState]);
    const { failedUploadsCount, invalidExtensionCount, exceededFileSizeCount } = React.useMemo(() => fileEntries.reduce((c, entry) => {
        var _a, _b;
        if ((_a = uploadState === null || uploadState === void 0 ? void 0 : uploadState[entry.file.name]) === null || _a === void 0 ? void 0 : _a.error) {
            c.failedUploadsCount++;
        }
        const ext = `.${(_b = entry.file.name.split(".").pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase()}`;
        if (!acceptedExtensions.includes(ext)) {
            c.invalidExtensionCount++;
        }
        if (maxFileSize && entry.file.size > maxFileSize) {
            c.exceededFileSizeCount++;
        }
        return c;
    }, { failedUploadsCount: 0, invalidExtensionCount: 0, exceededFileSizeCount: 0 }), [fileEntries, uploadState, acceptedExtensions, maxFileSize]);
    const removeInvalidFiles = () => setFileEntries((prev) => prev.filter((e) => e.state !== "warning"));
    const removeFile = React.useCallback((name) => {
        setFileEntries((prev) => prev.filter((e) => e.file.name !== name));
        resetUploadState();
    }, [resetUploadState]);
    return (_jsxs(_Fragment, { children: [_jsxs("div", Object.assign({ ref: ref, "data-testid": "upload-drop-area", className: cn(fileUploadVariants({ dragging, disabled }), className), onDragOver: (e) => {
                    e.preventDefault();
                    e.dataTransfer.dropEffect = "copy";
                }, onDragEnter: (e) => {
                    e.preventDefault();
                    if (!disabled) {
                        debouncedSetDragging(true);
                    }
                }, onDragLeave: (e) => {
                    e.preventDefault();
                    debouncedSetDragging(false);
                }, onDrop: handleDrop, onClick: () => {
                    if (!disabled && hiddenFileInputRef.current) {
                        hiddenFileInputRef.current.click();
                    }
                } }, props, { children: [_jsx("div", { className: cn("w-13 h-13 flex items-center justify-center rounded-full dark:bg-secondary-600", variant === "default" && "bg-primary-50", variant === "success" && "bg-success-50", variant === "warning" && "bg-warning-50", variant === "error" && "bg-error-50", disabled && "bg-secondary-100"), children: _jsx(ADPIcon, { size: "lg", icon: iconTypes[variant], className: cn("cursor-pointer", disabled
                                ? "text-secondary-300 cursor-not-allowed hover:text-secondary-300 dark:text-secondary-400 dark:bg-secondary-600"
                                : variant === "default"
                                    ? "text-primary-500 dark:text-primary-400"
                                    : variant === "success"
                                        ? "text-success-500 bg-success-50 dark:text-success-400 dark:bg-secondary-600"
                                        : variant === "error"
                                            ? "text-error-500 bg-error-50 dark:text-error-400 dark:bg-secondary-600"
                                            : "text-warning-500 bg-warning-50 dark:text-warning-400 dark:bg-secondary-600") }) }), _jsx("div", { className: "text-secondary-500 text-center text-md md:text-xl font-regular font-semibold dark:text-secondary-50", children: dropAreaCustomMessage !== null && dropAreaCustomMessage !== void 0 ? dropAreaCustomMessage : (_jsxs(_Fragment, { children: ["Drag & Drop file here", _jsxs("p", { className: "text-sm md:text-md text-secondary-400 font-normal font-regular dark:text-secondary-50", children: ["or click to browse", maxFileSize && _jsxs("span", { children: ["\u00A0(", readableFileSize(maxFileSize), " Max)"] })] }), _jsxs("p", { className: "text-sm md:text-md text-secondary-400 font-normal font-regular dark:text-secondary-50", children: ["Supported file types: ", acceptedExtensions.map((ext) => ext.replace(/^\./, "")).join(", ")] })] })) })] })), _jsx("input", { ref: hiddenFileInputRef, "data-testid": "file-upload-input", type: "file", multiple: multiple, onChange: handleFileSelection, accept: acceptedExtensions.join(","), className: "hidden" }), _jsxs("div", { className: "text-secondary-400 text-sm mt-3 flex flex-col items-start justify-start gap-1 dark:text-secondary-50", children: [infoText, failedUploadsCount > 0 && (_jsxs("p", { className: "flex items-center justify-center", children: [_jsx("span", { className: "me-1", children: `${failedUploadsCount} upload(s) failed. ` }), retryFailedUpload && _jsx(Button, { onClick: retryFailedUpload, variant: "text", color: "primary", size: "sm", prefixIcon: "sync", children: "Retry" })] })), (invalidExtensionCount > 0 || exceededFileSizeCount > 0) && multiple && (_jsxs("p", { className: "flex items-center justify-center", children: [_jsxs("span", { className: "me-1", children: [invalidExtensionCount > 0 && `${invalidExtensionCount} file(s) have invalid extensions `, invalidExtensionCount > 0 && exceededFileSizeCount > 0 && "and ", exceededFileSizeCount > 0 && `${exceededFileSizeCount} file(s) exceeded the file size limit. `] }), _jsx(Button, { onClick: removeInvalidFiles, variant: "text", color: "error", size: "sm", prefixIcon: "delete", children: "Remove" })] }))] }), fileEntries.length > 0 && (_jsx("div", { className: "w-full flex flex-col gap-4 mt-4", children: fileEntries.map((entry) => (_jsx(StatusCard, { fileEntry: entry, uploadState: uploadState, removeFile: removeFile, maxFileSize: maxFileSize, disabled: disabled, acceptedExtensions: acceptedExtensions }, entry.file.name))) }))] }));
});
FileUpload.displayName = "FileUpload";
//# sourceMappingURL=fileUpload.js.map