import { h, defineComponent, computed, inject } from 'vue';
import { CancelIcon, TrashIcon, AttachIcon, RetryIcon, DownloadIcon } from '../../_internal/icons';
import { NButton } from '../../button';
import { NIconSwitchTransition, NBaseIcon } from '../../_internal';
import { warn } from '../../_utils';
import NUploadProgress from './UploadProgress';
import { uploadInjectionKey } from './interface';
export default defineComponent({
    name: 'UploadFile',
    props: {
        clsPrefix: {
            type: String,
            required: true
        },
        file: {
            type: Object,
            required: true
        }
    },
    setup(props) {
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const NUpload = inject(uploadInjectionKey);
        const progressStatusRef = computed(() => {
            const { file } = props;
            if (file.status === 'finished')
                return 'success';
            if (file.status === 'error')
                return 'error';
            return 'info';
        });
        const buttonTypeRef = computed(() => {
            const { file } = props;
            if (file.status === 'error')
                return 'error';
            return undefined;
        });
        const showProgressRef = computed(() => {
            const { file } = props;
            return file.status === 'uploading';
        });
        const showCancelButtonRef = computed(() => {
            if (!NUpload.showCancelButtonRef.value)
                return false;
            const { file } = props;
            return ['uploading', 'pending', 'error'].includes(file.status);
        });
        const showRemoveButtonRef = computed(() => {
            if (!NUpload.showRemoveButtonRef.value)
                return false;
            const { file } = props;
            return ['finished'].includes(file.status);
        });
        const showDownloadButtonRef = computed(() => {
            if (!NUpload.showDownloadButtonRef.value)
                return false;
            const { file } = props;
            return ['finished'].includes(file.status);
        });
        const showRetryButtonRef = computed(() => {
            if (!NUpload.showRetryButtonRef.value)
                return false;
            const { file } = props;
            return ['error'].includes(file.status);
        });
        function handleRetryClick() {
            NUpload.submit(props.file.id);
        }
        function handleRemoveOrCancelClick(e) {
            e.preventDefault();
            const { file } = props;
            if (['finished', 'pending', 'error'].includes(file.status)) {
                handleRemove(file);
            }
            else if (['uploading'].includes(file.status)) {
                handleAbort(file);
            }
            else {
                warn('upload', 'The button clicked type is unknown.');
            }
        }
        function handleDownloadClick(e) {
            e.preventDefault();
            handleDownload(props.file);
        }
        function handleRemove(file) {
            const { XhrMap, doChange, onRemoveRef: { value: onRemove }, mergedFileListRef: { value: mergedFileList } } = NUpload;
            void Promise.resolve(onRemove
                ? onRemove({
                    file: Object.assign({}, file),
                    fileList: mergedFileList
                })
                : true).then((result) => {
                if (result === false)
                    return;
                const fileAfterChange = Object.assign({}, file, {
                    status: 'removed'
                });
                XhrMap.delete(file.id);
                doChange(fileAfterChange, undefined, {
                    remove: true
                });
            });
        }
        function handleDownload(file) {
            const { onDownloadRef: { value: onDownload } } = NUpload;
            void Promise.resolve(onDownload ? onDownload(Object.assign({}, file)) : true).then((res) => {
                /** I haven't figure out its usage, so just leave it here */
            });
        }
        function handleAbort(file) {
            const { XhrMap } = NUpload;
            const XHR = XhrMap.get(file.id);
            XHR === null || XHR === void 0 ? void 0 : XHR.abort();
            handleRemove(Object.assign({}, file));
        }
        return {
            mergedTheme: NUpload.mergedThemeRef,
            progressStatus: progressStatusRef,
            buttonType: buttonTypeRef,
            showProgress: showProgressRef,
            disabled: NUpload.disabledRef,
            showCancelButton: showCancelButtonRef,
            showRemoveButton: showRemoveButtonRef,
            showDownloadButton: showDownloadButtonRef,
            showRetryButton: showRetryButtonRef,
            handleRemoveOrCancelClick,
            handleDownloadClick,
            handleRetryClick
        };
    },
    render() {
        const { clsPrefix, mergedTheme } = this;
        return (h("a", { ref: "noopener noreferer", target: "_blank", href: this.file.url || undefined, class: [
                `${clsPrefix}-upload-file`,
                `${clsPrefix}-upload-file--${this.progressStatus}-status`,
                this.file.url && `${clsPrefix}-upload-file--with-url`
            ] },
            h("div", { class: `${clsPrefix}-upload-file-info` },
                h("div", { class: `${clsPrefix}-upload-file-info__name` },
                    h(NBaseIcon, { clsPrefix: clsPrefix }, { default: () => h(AttachIcon, null) }),
                    this.file.name),
                h("div", { class: `${clsPrefix}-upload-file-info__action` },
                    (this.showRemoveButton || this.showCancelButton) &&
                        !this.disabled && (h(NButton, { key: "cancelOrTrash", theme: mergedTheme.peers.Button, themeOverrides: mergedTheme.peerOverrides.Button, text: true, type: this.buttonType, onClick: this.handleRemoveOrCancelClick }, {
                        icon: () => (h(NIconSwitchTransition, null, {
                            default: () => this.showRemoveButton ? (h(NBaseIcon, { clsPrefix: clsPrefix, key: "trash" }, { default: () => h(TrashIcon, null) })) : (h(NBaseIcon, { clsPrefix: clsPrefix, key: "cancel" }, { default: () => h(CancelIcon, null) }))
                        }))
                    })),
                    this.showRetryButton && !this.disabled && (h(NButton, { key: "retry", text: true, type: this.buttonType, onClick: this.handleRetryClick, theme: mergedTheme.peers.Button, themeOverrides: mergedTheme.peerOverrides.Button }, {
                        icon: () => (h(NBaseIcon, { clsPrefix: clsPrefix }, { default: () => h(RetryIcon, null) }))
                    })),
                    this.showDownloadButton ? (h(NButton, { key: "download", text: true, type: this.buttonType, onClick: this.handleDownloadClick, theme: mergedTheme.peers.Button, themeOverrides: mergedTheme.peerOverrides.Button }, {
                        icon: () => (h(NBaseIcon, { clsPrefix: clsPrefix }, { default: () => h(DownloadIcon, null) }))
                    })) : null)),
            h(NUploadProgress, { show: this.showProgress, percentage: this.file.percentage || 0, status: this.progressStatus })));
    }
});
