<template>
    <div :class="prefixCls" v-yyloading="readingFile">
        <div :class="prefixCls + '-choose'">
            <Upload
                :before-upload="beforeUpload"
                :show-upload-list="false"
                :max-size="maxSize"
                :max-count="maxCount"
                :disabled="disabled"
                :multiple="maxCount != 1"
                action="security-upload">
                <YYButton type="ghost" :disabled="disabled ? true : false">{{title || t('upload.addFile')}}</YYButton>
                <span :class="prefixCls + '-choose-tips'">({{t('upload.singleMaxSize').replace('s1%', maxSize/1024)}})</span>
            </Upload>
            <div :class="prefixCls + '-choose-content'">
                <slot name="chooseContent"></slot>
            </div>
        </div>
        <div :class="prefixCls + '-drag'" v-if="showDrag">
            <Upload
                :before-upload="beforeUpload"
                :show-upload-list="false"
                :max-size="maxSize"
                :max-count="maxCount"
                action="security-upload"
                multiple
                :disabled="disabled"
                type="drag">
                <div :class="[prefixCls + '-drag-content', {[`${prefixCls}-drag-content-disabled`]: disabled}]">
                    <slot name="dragContent" v-if="!files.length">
                        <span :class="prefixCls + '-drag-content-text'">{{t('upload.dragFilesHereToUpload')}}</span>
                    </slot>
                    <div :class="prefixCls + '-drag-list'" ref="sortableWrapper" v-else>
                        <div 
                            @click.stop
                            v-for="(item, index) in files"
                            :class="[prefixCls + '-item', 'sortable-item']" 
                            :key="'' + index">
                            <YYRadioGroup v-if="!disabledSecurity && !hideSecurity" v-model="item.security">
                                <YYRadio 
                                    v-for="(value, key) in fileSecurity" 
                                    :disabled="item.disabled || item.lastFileFlag"
                                    :key="key" 
                                    :label="key">{{value.text}}</YYRadio>
                            </YYRadioGroup>
                            <YYRadio v-else-if="!hideSecurity" :value="true" disabled>{{commonSecurity[security || 'PUBLIC'].text}}</YYRadio>
                            <YYCheckbox v-model="item.downloadEnable" v-if="!disabledDownload" :disabled="item.lastFileFlag">{{t('upload.allowDownload')}}</YYCheckbox>
                            <div :class="prefixCls + '-item-info'">
                                <YYFileLogo :type="getType(item.fileName)"></YYFileLogo>
                                <span :class="prefixCls + '-item-filename'" :title="item.fileName">{{item.fileName}}</span>
                                <span 
                                    v-if="item.downloadEnable && item.lastFileFlag"
                                    :class="prefixCls + '-item-download'" 
                                    @click="handleDownload(item)">{{t('upload.download')}}</span>
                                <span 
                                    v-if="item.lastFileFlag"
                                    :class="prefixCls + '-item-download'" 
                                    @click="handlePreview(item)">{{t('upload.preview')}}</span>

                                <span :class="prefixCls + '-item-filesize'">{{item.fileSize | bytesToSize}}</span>
                                <YYIcon type="close" @click.native="handleRemoveFile(item, index)"></YYIcon>
                            </div>
                        </div>
                    </div>
                </div>
            </Upload>
        </div>
        <!-- <div :class="prefixCls + '-list'" v-if="showUploadList">
            <div 
                v-for="(item, index) in lastFileFormData"
                :class="prefixCls + '-item'" 
                :key="item.fileId">
                <YYRadioGroup v-model="item.security">
                    <YYRadio 
                        v-for="(value, key) in fileSecurity" 
                        disabled
                        :key="key" 
                        :label="key">{{value.text}}</YYRadio>
                </YYRadioGroup>
                <YYCheckbox 
                    v-model="item.downloadEnable" 
                    disabled 
                    v-if="!disabledDownload">{{t('upload.allowDownload')}}</YYCheckbox>
                <div :class="prefixCls + '-item-info'">
                    <YYFileLogo :type="getType(item.fileName)"></YYFileLogo>
                    <span :class="prefixCls + '-item-filename'">{{item.fileName}}</span>
                    <span 
                        v-if="item.downloadEnable"
                        :class="prefixCls + '-item-download'" 
                        @click="handleDownload(item)">{{t('upload.download')}}</span>
                    <span 
                        :class="prefixCls + '-item-download'" 
                        @click="handlePreview(item)">{{t('upload.preview')}}</span>
                    <span :class="prefixCls + '-item-filesize'">{{item.fileSize | bytesToSize}}</span>
                    <YYIcon type="close" @click.native="handleRemoveLastFile(item, index)"></YYIcon>
                </div>
            </div>
        </div> -->
        <YYLoading v-model="loading" :text="`${t('upload.fileUploading')}${progress}`"> </YYLoading>
    </div>
</template>
<script>
    import { deepCopy, bytesToSize } from '../../../utils/assist'
    import axios from 'axios'
    import Upload from '../../base/upload/'
    import YYIcon from '../../base/icon/'
    import YYCheckbox from '../../base/checkbox/'
    import YYLoading from '../../base/loading/'
    import YYRadio from '../../base/radio/'
    import YYFileLogo from '../../base/file-logo/'
    import YYMessage from '../../base/message/'
    import Sortable from 'sortablejs'
    import Locale from '../../../mixins/locale'

    import { calcFileMd5 } from './utils';

    const prefixCls = 'yy-security-upload'

    let uuid = 0
    function getUUID() {
        return ++uuid + '';
    }
    export default {
        name: 'YYSecurityUploadSortAll',
        mixins: [ Locale ],
        components: {
            Upload,
            YYIcon,
            YYCheckbox,
            YYRadio,
            YYLoading,
            YYRadioGroup: YYRadio.YYRadioGroup,
            YYFileLogo
        },
        props: {
            title: {
                type: String,
                default: ''
            },
            objectName: {
                type: String,
                required: true
            },
            showDrag: {
                type: Boolean,
                default: true
            },
            objectId: {
                type: String | Number,
                required: true
            },
            lastId: {
                type: String | Number
            },
            maxSize: {
                type: Number | String,
                default: 300 * 1024
            },
            maxCount: {
                type: Number,
                default: 99999
            },
            security: {
                type: String
            },
            host: {
                type: String,
                default: 'http://ezone.imp.pub.caep'
                // default: '//ezone.pub-dev.caep'
            },
            disabledSecurity: { // 上传是否禁止显示密级
                type: Boolean,
                default: false
            },
            hideSecurity: {
                type: Boolean,
                default: false
            },
            disabledDownload: { // 上传是否禁止显示允许下载
                type: Boolean,
                default: false
            },
            defaultAllowDownload: {
                type: Boolean,
                default: false
            },
            disabled: {
                type: Boolean,
                defaults: false
            },
            showUploadList: {
                type: Boolean,
                default: true
            }
        },
        data() {
            return {
                prefixCls,
                commonSecurity: { // 密级
                    PUBLIC: {
                        limit: 0,
                        text: this.t('upload.public')
                    },
                    INTERNAL: {
                        limit: 1,
                        text: this.t('upload.internal')
                    },
                    SECRET: {
                        limit: 2,
                        text: this.t('upload.secret')
                    },
                    CONFIDENTIAL: {
                        limit: 3,
                        text: this.t('upload.confidential')
                    }
                },
                files: [],
                fileData: {},
                deleteFileIds: [],
                progress: '0%',
                loading: false,
                isIe: false,
                readingFile: false
            }
        },
        filters: {
            bytesToSize
        },
        computed: {
            fileSecurity() { // 计算附件密级
                let result = {}
                for(const key in this.commonSecurity) {
                    const data = this.commonSecurity[key]
                    if(!this.security || this.commonSecurity[this.security].limit >= data.limit) {
                        result[key] = data
                    }
                }
                // 监听附件密级
                if(this.security) {
                    this.files.forEach(item => {
                        if(this.commonSecurity[item.security] 
                        && (this.commonSecurity[this.security].limit < this.commonSecurity[item.security].limit)) {
                            item.security = ''
                        }
                    })
                }
                return result
            }
        },
        watch: {
            lastId: {
                immediate: true,
                handler: function () {
                    this.getLastFileFormData() 
                }
            }
        },
        methods: {
            getType(data) {
                if(typeof data != 'string') return ''
                return data.split('.').pop().toLocaleLowerCase() || ''
            },
            getLastFileFormData() {
                if(this.lastId) {
                    const action = `${this.host}/cooperation/rest/v1/file/security/${this.objectName}/${this.lastId}`
                    axios.get(action, {
                        withCredentials: true
                    }).then(res => {
                        if (res && res.data && res.data.data) {
                            res.data.data.forEach(file => {
                                file.lastFileFlag = true
                            })
                            this.$set(this, 'fileData', {})
                            this.files = res.data && res.data.data || []
                            this.sortable()
                        }
                    })
                }
            },
            getSize() { // 获取所有附件大小
                const files = this.getFiles()
                if(files.length <= 1) {
                    return files[0] ? files[0].fileSize : 0
                }
                return this.getFiles().reduce((a, b) => {
                    return (a.fileSize || a) + b.fileSize
                })
            },
            getMaxSecurity() { // 获取当前不可变更附件最高密级
                let security = 0
                this.lastFileFormData.forEach(item => {
                    const limit = this.commonSecurity[item.security].limit
                    if(limit > security) {
                        security = limit
                    }
                })
                return security
            },
            getFiles() { // 获取所有files
                return this.files
            },
            handleRemoveFile(item, key) { // 删除当前上传文件
                this.files.splice(key, 1)
                if (item.lastFileFlag) this.deleteFileIds.push(item.fileId)
                else this.$delete(this.fileData, item.randomId)
                this.$emit('on-file-remove', item)
            },
            handleClearFile() {
                this.files = []
                this.getLastFileFormData()
            },
            handleDownload(data) {
                if (this.isIe) {
                    YYMessage.warning('请切换到360极速模式')
                    return
                }
                const action = `${this.host}/cooperation/rest/v1/file/security/${data.fileId}/url/download?businessId=${this.objectId}&businessType=${this.objectName}`
                YYLoading.show()
                axios.get(action, {
                    withCredentials: true
                }).then(res => {
                    YYLoading.hide()
                    if(res.data && res.data.url) {
                        window.open(res.data.url, '_blank')
                    }
                }).catch((error) => {
                    YYLoading.hide()
                })
            },
            handlePreview(data) {
                if (this.isIe) {
                    YYMessage.warning('请切换到360极速模式')
                    return
                }
                const action = `${this.host}/cooperation/rest/v1/file/security/${data.fileId}/url/preview?businessId=${this.objectId}&businessType=${this.objectName}`
                YYLoading.show()
                axios.get(action, {
                    withCredentials: true
                }).then(res => {
                    YYLoading.hide()
                    if(res.data && res.data.url) {
                        window.open(res.data.url, '_blank')
                    }
                }).catch((error) => {
                    YYLoading.hide()
                })
            },
            handleStartUpLoad() {
                return new Promise((resolve, reject) => {
                    // 没有附件时直接resolve
                    if(!this.files.length && !this.deleteFileIds.length) return resolve(true)
                    
                    // 判断是否选择附件密级
                    let security = true

                    // FIXME
                    const newFiles = []
                    this.files.forEach((item) => {
                        if (!item.lastFileFlag) {
                            if(this.disabledSecurity) {
                                item.security = this.security || 'PUBLIC'
                            }
                            if(this.disabledDownload) {
                                item.downloadEnable = true
                            }
                            if(!item.security) {
                                security = false
                            }
                            newFiles.push(item)
                        }
                    })
                    if(!security) {
                        YYMessage.warning(this.t('upload.pleaseSelectFileSecretLevel'))
                        return resolve(false)
                    }

                    let formData = new FormData()
                    Object.keys(this.fileData).forEach(key => {
                        formData.append('files', this.fileData[key])
                    })
                    formData.append('params', JSON.stringify(newFiles))

                    // // 更换当前已存在fileId的objectId映射
                    // if(this.lastFileFormData.length) {
                    //     const fileIds = this.lastFileFormData.map(item => {
                    //         return item.fileId
                    //     })
                    //     formData.append('fileIds', JSON.stringify(fileIds))
                    // }

                    formData.append('fileIds', JSON.stringify(this.files.map(e => e.fileId || e.randomId)))

                    // 更新已删除文件
                    if(this.deleteFileIds.length) {
                        formData.append('deleteFileIds', JSON.stringify(this.deleteFileIds))
                    }
                    
                    const action = `${this.host}/cooperation/rest/v1/file/security/${this.objectName}/${this.objectId}`
                    this.loading = true
                    axios.defaults.timeout = 1000 * 60 * 60 * 24
                    axios.post(action, formData, {
                        withCredentials: true,
                        onUploadProgress: (progress) => {
                            this.progress = Math.round(progress.loaded / progress.total * 100) + '%'
                        }
                    }).then(res => {
                        this.loading = false
                        this.handleClearFile();
                        resolve(res.data)
                    }).catch(()=> {
                        this.loading = false
                        YYMessage.error(this.t('upload.fileUploadFailed'))
                        resolve(false)
                    })
                })
            },
            sortable() {
                this.$nextTick().then(()=>{
                    const wrapper = this.$refs.sortableWrapper
                    const handle = `.sortable-item`
                    if(wrapper && handle) {
                        Sortable.create(wrapper, {
                            group: {
                                name: 'upload',
                                pull: false,
                                put: true
                            },
                            handle: handle,
                            onUpdate:  (evt) => {
                                this.handleDragUpdate(evt)
                            },
                            animation: 150
                        })
                    }
                })
            },
            removeNode(node) { // 移除节点
                node.parentElement.removeChild(node)
            },
            insertNodeAt(fatherNode, node, position) { // 插入节点
                let refNode = position === 0 ? fatherNode.children[0] : fatherNode.children[position - 1].nextSibling
                fatherNode.insertBefore(node, refNode)
            },
            handleDragUpdate(evt, data) { // 更新数据的时候
                this.removeNode(evt.item)
                this.insertNodeAt(evt.from, evt.item, evt.oldIndex)
                
                this.files.splice(evt.newIndex, 0, this.files.splice(evt.oldIndex, 1)[0])
                this.$emit('on-sort', this.getFiles())
            },
            beforeUpload (file) {
                if (this.maxCount && this.files.length + 1 > this.maxCount) {
                    YYMessage.error(this.t('upload.upToCountFilesCanBeUploaded').replace('s1%', this.maxCount))
                    return false
                }
                if(file.size > this.maxSize * 1024) {
                    YYMessage.error(this.t('upload.fileExceedsSizeLimit'))
                    return false
                }
                if (file.size == 0) {
                    YYMessage.error('上传附件内容不能为空，请重新上传')
                    return false
                }

                this.readingFile = true;
                // 计算文件md5
                calcFileMd5(file).then(md5 => {
                    const param = {
                        fileSize: file.size,
                        fileName: file.name,
                        downloadEnable: !!this.defaultAllowDownload,
                        security: '',
                        disabled: false,
                        randomId: getUUID(),
                        md5
                    }
                    this.fileData[param.randomId] = file
                    if(!this.disabledSecurity) { // 当外部禁止显示密级时
                        const fileName = file.name && file.name.substr(0, 2) || ''
                        Object.keys(this.commonSecurity).forEach(key => {
                            if(this.commonSecurity[key].text === fileName) { //密级名称相等
                                if(!this.security) { // 外部没有传密级
                                    param.security = key
                                    param.disabled = true
                                } else {
                                    if(this.commonSecurity[this.security].limit >= this.commonSecurity[key].limit) {
                                        param.security = key
                                        param.disabled = true
                                    }
                                }
                            } 
                        })
                    }
                    this.files.push(param)
                    this.sortable()
                    this.$emit('on-change', this.getFiles());
                    this.readingFile = false;
                }).catch(err => {
                    YYMessage.error('文件读取失败' + err.message);
                    this.readingFile = false;
                })

                return false
            }
        },
        created() {
            if (!!window.ActiveXObject || "ActiveXObject" in window) this.isIe = true
        }
    }
</script>