<template>
    <div class="mix-upload-container">
        <input v-model="currentValue" type="hidden" />
        <bgo-form-item
            :label="label"
            :required="uploadRequired"
            :readonly="readonly"
            :disabled="disabled"
            :tip="
                uploadTipText ||
                `注：单个文件大小不超过:${getMaxUploadSize()}，最多支持上传${limit}个文件。`
            ">
            <div class="upload-items-container">
                <div v-if="listType === 'text'">
                    <bgo-file-item
                        v-for="(iconFile, index) in iconFileList"
                        :key="'image-view-' + index"
                        :file-name="iconFile.name"
                        :size="iconFile.size"
                        @click="openFileUrl(iconFile)">
                        <template #action v-if="isOperate">
                            <van-icon
                                name="clear"
                                color="#BFC1C2"
                                @click="onDeleteFile(index, iconFile.name)" />
                        </template>
                    </bgo-file-item>

                    <van-uploader
                        v-if="!disabled && !readonly"
                        :accept="getAccept"
                        :multiple="supportMultiple"
                        :disabled="disabled"
                        :max-size="maxSize"
                        :max-count="limit"
                        :upload-icon="calUploadIcon"
                        :after-read="onChangeAfter"
                        :before-read="onChangeBefore"
                        @oversize="onOverSize"
                        ref="uploader">
                        <div class="uploader__button">
                            <van-icon
                                name="plus"
                                size="18px"
                                color="#BFC1C2" />
                        </div>
                    </van-uploader>
                </div>

                <div v-if="listType === 'picture'">
                    <div
                        v-for="(iconFile, index) in iconFileList"
                        :key="'image-view-' + index"
                        class="upload-items-image">
                        <img
                            :src="iconFile.content"
                            class="upload-items-image__img"
                            @click="onClickListPreview(iconFile, index)" />
                        <van-icon
                            v-if="isOperate"
                            name="clear"
                            size="16"
                            class="upload-items-image__close-icon"
                            @click="onDeleteFile(index, iconFile.name)" />
                    </div>

                    <van-uploader
                        v-if="!disabled && !readonly"
                        :accept="getAccept"
                        :multiple="supportMultiple"
                        :disabled="disabled"
                        :max-size="maxSize"
                        :max-count="limit"
                        :upload-icon="calUploadIcon"
                        :after-read="onChangeAfter"
                        :before-read="onChangeBefore"
                        :capture="capture"
                        @oversize="onOverSize"
                        ref="uploader">
                        <div class="uploader__button">
                            <van-icon
                                name="plus"
                                size="18px"
                                color="#BFC1C2" />
                        </div>
                    </van-uploader>
                </div>
            </div>
        </bgo-form-item>
    </div>
</template>

<script>
    import {FieldMixin} from "vant/lib/mixins/field";
    import { commonFormComponentMixin } from "../../mixins/form.component";
    import {getFileSize, getFileSuffix, isEmpty, isNotEmpty,
        LOCAL_ATT_DOWNLOAD_URL_PREFIX,
        LOCAL_ATT_VIEW_URL_PREFIX,
        API_ATT_VIEW_URL_PREFIX,
        API_ATT_DOWNLOAD_URL_PREFIX
    } from "@bingoit/utils";
    import {closeLoading, showLoading, showMsg, alert} from "../../utils/common.ui";
    import { ImagePreview } from 'vant';
    import BgoFileItem from '../../FileItem/src/index'

    import {getAutoConvert} from "@bingoit/ajax";
    import { getFileTypeIcon } from '../../utils/filetype.icon';
    import { upload } from "./util";

    import "./index.scss";

    const HAS_FILE_FLAG = "!!!HAS_FILE!!!";

    export default {
        name: "BgoUpload",
        components: { BgoFileItem },
        props: {
            accept: String,
            action: {
                type: String,
                require: true
            },
            //上传的文件字段名
            name: {
                type: String,
                default: 'uploadFile'
            },
            multiple: {
                type: Boolean,
                default: false
            },
            limit: {
                type: Number,
                default: 1
            },
            maxSize: {
                type: Number,
                default: 10 * 1024 * 1024 //5M
            },
            listType: {
                type: String,
                default: 'text',
                validator: function (value) {
                    return ['text', 'picture'].indexOf(value) !== -1
                }
            },
            uploadTipText: {
                type: String,
                default: ''
            },
            delFilePromptText: {
                type: String,
                default: '您确定要删除已上传的问题吗？'
            },
            args: [String, Object],

            //图片选取模式，可选值为 camera (直接调起摄像头)
            capture: String,
            uploadIcon: {
                type: String,
                default: 'photograph'
            },
            //是否自动上传
            autoUpload: {
                type: Boolean,
                default: false
            },
            isTriggerCreated: {
                type: Boolean,
                default: false
            },
            // fileListMode: {
            //     type: String,
            //     default: 'detail',
            //     validator(value) {
            //         return ['detail', 'thumbnail'].indexOf(value) !== -1;
            //     }
            // }
        },
        mixins: [ commonFormComponentMixin, FieldMixin ],
        computed: {
            deletable() {
                return !this.disabled && !this.readonly;
            },
            supportMultiple() {
                return this.limit > 1;
            },
            calUploadIcon() {
                if(this.uploadIcon === 'photograph' && this.listType === 'text') {
                    return 'plus';
                } else {
                    return this.uploadIcon;
                }
            },
            getAccept() {
                if(this.listType === 'picture' && isEmpty(this.accept)) {
                    return "image/*";
                } else {
                    if(isEmpty(this.accept)) {
                        return "*";
                    }
                    return this.accept;
                }
            },
            isOperate() {
                return !this.disabled && !this.readonly;
            }
        },
        mounted() {
            this.initFiles();
            if(this.isTriggerCreated) {
                this.$emit('created', this);
            }
        },
        data() {
            return {
                uploadRequired: this.required && !this.disabled,
                showReviewFile: false,
                currentValue: this.value,
                fileList: [],
                iconFileList: [],
                isPreview: false,
                previewImgSrc: '',
                previewTop: 0,
                notUploadFileNum: 0,
                // 是否是组件内部变更currentValue
                innerChange: false,
            }
        },
        watch: {
            currentValue() {
                if (this.currentValue === HAS_FILE_FLAG) {
                    return;
                }
                // 内部变更，不触发文件初始化
                if (this.innerChange) {
                    this.innerChange = false;
                    return;
                }

                this.iconFileList = [];
                this.initFiles();
            },
        },
        methods: {
            isText() {
                return this.listType === 'text';
            },
            onChangeBefore() {
                showLoading('正在加载...');
                return true;
            },
            //判断是否需要上传
            isNeedUpload() {
                if (this.disabled || this.readonly) {
                    return false;
                } else {
                    return this.fileList.some(item => {
                        return item.status === "ready"
                            || item.status === "uploading"
                    });
                }
            },
            /**
             * 获取未上传文件数量
             */
            getNotUploadFileNum() {
                return this.notUploadFileNum;
            },
            /**
             *  初始化已经上传的文件
             */
            initFiles: function() {
                if(isNotEmpty(this.value)) {
                    if(Array.isArray(this.value)) {
                        let firstObj = this.value[0];
                        if(typeof(firstObj) !== 'string') {
                            this.handleFilePath(this.value);
                            return;
                        }
                    } else if(typeof(this.value) !== 'string') {
                        this.handleFilePath([this.value]);
                        return;
                    }
                    getAutoConvert('/api/attachment/bypath', {path: this.value}).then(response => {
                        if(response.code === 1) {
                            this.handleFilePath(response.datas);
                        }
                    }).catch(error => {
                        console.error(JSON.stringify(error));
                    });
                }
            },
            handleFilePath(fileItems) {
                if(!fileItems || fileItems.length === 0) {
                    return;
                }
                fileItems.forEach(res => {
                    let url = res.url;
                    if(isNotEmpty(url) && !url.startsWith('http://') && !url.startsWith('https://')
                        && (url.startsWith(LOCAL_ATT_DOWNLOAD_URL_PREFIX)
                            || url.startsWith(LOCAL_ATT_VIEW_URL_PREFIX))) {
                        if(url.startsWith(LOCAL_ATT_DOWNLOAD_URL_PREFIX)) {
                            url = url.replace(LOCAL_ATT_DOWNLOAD_URL_PREFIX, API_ATT_DOWNLOAD_URL_PREFIX);
                        } else if(url.startsWith(LOCAL_ATT_VIEW_URL_PREFIX)) {
                            url = url.replace(LOCAL_ATT_VIEW_URL_PREFIX, API_ATT_VIEW_URL_PREFIX);
                        }
                        if(!url.startsWith("/")) {
                            url = "/" + url;
                        }
                    }
                    this.handleFileIcon({uid: res.id, name: res.name, size: res.size, url: url, path: url});
                });
            },
            onChangeAfter(files) {
                closeLoading();
                if(files.length > this.limit || this.fileList.length >= this.limit) {
                    alert('最多只支持上传' + this.limit + '个文件.');
                    return false;
                }

                // 新增待上传文件
                this.notUploadFileNum += 1;

                // 空值,设置特殊值以通过表单校验
                // 特殊值在上传前会被清除
                if (isEmpty(this.currentValue) && !this.autoUpload) {
                    this.currentValue = HAS_FILE_FLAG;
                }

                if(files.length > 1) {
                    files.forEach((file) => {
                        this.fileList.push({file: file.file, content: file.content, status: "ready"});
                        this.handleFileIcon({name: file.file.name, size: file.file.size, url:'', path: file.content});
                    });
                } else {
                    this.fileList.push({file: files.file, content: files.content, status: "ready"});
                    this.handleFileIcon({name: files.file.name, size: files.file.size, url:'', path: files.content});
                }
                if(this.autoUpload) {
                    this.startUpload(this.args);
                }
            },
            onClickListPreview(iconFile, index) {
                if(!iconFile.isImage) {
                    return false;
                }
                let images = new Array();
                let countIndex = 0;
                this.iconFileList.forEach((file) => {
                    if(file.isImage) {
                        images.push(file.content);
                    } else {
                        if(index > countIndex) {
                            countIndex++;
                        }
                    }
                });
                ImagePreview({
                    images: images,
                    startPosition: index - countIndex,
                    closeable: true,
                });
            },
            onDeleteFile: function (index, name) {
                if(this.fileList.length > 0 ) {
                    // FIXME: 通过文件名查找文件是有问题的，目前没有找到更好的解决方法
                    let fileIndex = -1;
                    for(let i = 0; i < this.fileList.length; i++) {
                        if (this.fileList[i].file.name === name) {
                            fileIndex = i;
                            break;
                        }
                    }

                    if (fileIndex !== -1) {
                        this.fileList.splice(fileIndex, 1);

                        // 删除新添加未上传的文件
                        this.notUploadFileNum -= 1;
                    }
                }
                // 删除所有文件后清除特殊值
                if (this.fileList.length === 0 && this.currentValue === HAS_FILE_FLAG) {
                    this.currentValue = "";
                    this.innerChange = true;
                }

                let url = this.iconFileList[index].url;
                if(isNotEmpty(url) && isNotEmpty(this.currentValue)) {
                    let valueTmp = this.currentValue.replace(url, '');
                    if(valueTmp.startsWith(',')) {
                        valueTmp = valueTmp.substring(1, valueTmp.length);
                    }
                    if(valueTmp.endsWith(',')) {
                        valueTmp = valueTmp.substring(0, valueTmp.length - 1);
                    }

                    if (valueTmp === "" && this.fileList.length !== 0) {
                        this.currentValue = HAS_FILE_FLAG;
                    } else {
                        this.currentValue = valueTmp;
                    }
                    this.innerChange = true;
                }
                this.iconFileList.splice(index, 1);
            },
            onOverSize() {
                closeLoading();
                showMsg('文件太大不支持上传');
            },
            /**
             * 上传文件
             * @param requestArgs 上传文件时的参数
             */
            startUpload(requestArgs) {
                //console.debug("开始上传文件...");
                return new Promise((resolve, reject) => {
                    if(isEmpty(this.action)) {
                        console.error('上传URL为空');
                        reject();
                    } else if(this.fileList.length === 0) {
                        //console.info('没有需要上传的文件');
                        reject();
                    } else {
                        //console.debug("正在上传文件,上传URL为:%s.", this.uploadUrl);
                        if(this.fileList.length > 0) {
                            let fileUrls = new Array();
                            let responseData = new Array();
                            // 额外参数
                            const param = Object.assign({}, this.args, requestArgs);

                            this.fileList.forEach((file) => {
                                if (file.status !== "ready") {
                                    return;
                                }

                                file.status = 'uploading';
                                file.message = '上传中...';

                                upload(this.action, file.file, param, this.name)
                                    .then(response=> {
                                        file.status = "done";
                                        file.message = "";
                                        fileUrls.push(response.data.url);
                                        responseData.push(response.data);
                                    }).catch(() => {
                                        file.status = "failed";
                                        file.message = '上传失败'
                                    }).finally(() => {
                                        this.notUploadFileNum -= 1;
                                        this.$emit('on-upload-complete', responseData);

                                        if(this.notUploadFileNum === 0) {
                                            // 上传完成后清除特殊值
                                            if(this.currentValue === HAS_FILE_FLAG) {
                                                this.currentValue = "";
                                            }

                                            if(isEmpty(this.currentValue)) {
                                                this.currentValue = fileUrls.join(',');
                                            } else {
                                                this.currentValue += ',' + fileUrls.join(',');
                                            }

                                            this.innerChange = true;

                                            resolve(responseData);
                                        }
                                    })
                            });
                        }
                    }
                });
            },
            openFileUrl(iconFile) {
                if(isNotEmpty(iconFile.url)) {
                    window.location.href = iconFile.url;
                }
            },
            getMaxUploadSize() {
                let size = getFileSize(this.maxSize);
                size = size.replace('.00', '');
                return size;
            },
            handleFileIcon: function(fileInfo) {
                let ext = getFileSuffix(fileInfo.name);
                if(isNotEmpty(ext)) {
                    ext = ext.toLowerCase();
                    let path = '';
                    let isImage = false;

                    path = getFileTypeIcon(ext);
                    if(['gif', 'jpg', 'png', 'jpeg'].indexOf(ext) !== -1) {
                        isImage = true;
                        path = fileInfo.path
                    }

                    this.iconFileList.push({
                        uid: fileInfo.uid,
                        name: fileInfo.name,
                        isImage: isImage,
                        content: path,
                        size: getFileSize(fileInfo.size),
                        url: fileInfo.url
                    });
                }
            },
            changeFormValidatePropRules(formPropRules) {
                //this.validatePropRules = formPropRules;
                let isRequired = false;
                if(formPropRules && !this.disabled) {
                    for(let rule of formPropRules) {
                        if(rule.required) {
                            isRequired = rule.required;
                            break;
                        }
                    }
                }
                this.uploadRequired = isRequired;
            },
            getSourceElement() {
                return this.$refs.uploader
            }
        }
    }
</script>
