<template>
    <Panel name="upload" :class="bem()" @close="toPc">
        <template slot="tab" slot-scope="{active}">
            <slot name="label" :active="active">
                <Icon name="upload" />
                <span>传图片</span>
            </slot>
        </template>

        <template slot="title">
            <slot name="title"/>
        </template>

        <slot>
            <div :class="bem('header')">
                <slot name='header'>
                    <pre :class="bem('title')">{{title[status]}}</pre>
                    <sub :class="bem('desc')">{{desc}}</sub>
                </slot>
            </div>
            <div :class="bem('body')">
                <template  v-if="status === 'pc'">
                    <slot name="local-upload" :onUploaded="onUploaded" :log="log">
                        <upload
                            autoUpload
                            multiple
                            :beforeUpload="handleBeforeUpload"
                            :accept="accept"
                            ref="upload"
                            :concurrent="1"
                            @change="onChange"
                            @remove="onRemove"
                            @success="onUploaded"
                            @error="onError"
                        >
                            <Button rect size="large" type="primary" :class="bem('upload-btn')">上传</Button>
                        </upload>
                    </slot>
                    <Button type="text" size="small" @click="toQr">上传手机图片</Button>
                </template>
                <template v-else-if="status === 'qr'">
                    <qrcode :class="bem('qrcode')" :value="qrcode_url" :options="qrcodeOption" />
                    <div :class="bem('qrcode-desc')">扫一扫二维码上传</div>
                    <Button :class="bem('back-pc')" type="text" size="small" @click="toPc">
                        &lt;返回本地上传
                    </Button>
                </template>
                <template v-else-if="status === 'mobile'">
                    <img :class="bem('qrcode-scaned')" src="../../assets/img/editor/qrcode-scaned.png" alt="">
                    <Button :class="bem('back-pc')" type="text" size="small" @click="toQr">
                        &lt;重新扫描二维码
                    </Button>
                </template>
            </div>
            <div :class="bem('footer')" v-if="status === 'pc'">
                <Button @click="showModal = !showModal" type="text" size="small">网址上传 / 剪贴板上传 / 拖拽上传</Button>
            </div>
            <Modal
                theme="dark"
                :visible.sync="showModal"
                :append-body="false"
                transitionName="gd-upload-modal-fade"
                :transition-duration="{ enter: 300, leave: 300 }"
                width="100%"
                top="auto"
                bottom="0"
                :class="[bem('upload-modal')]"
            >

                <div :class="bem('upload-modal-title')">拖拽上传</div>
                <div :class="bem('upload-modal-desc')">将图片<u>拖拽到画布</u>，完成上传。</div>

                <div :class="bem('upload-modal-title')">剪贴板上传</div>
                <div :class="bem('upload-modal-desc')">使用<u>CTRL+V</u>，可直接粘贴剪贴板图片到画布。</div>

                <div :class="bem('upload-modal-title')">网址上传</div>
                <div :class="bem('url-upload')">
                    <input v-model.trim="externalImg" type="input" placeholder="http://">
                    <Button @click="uploadExternalImg" rect size="small">上传</Button>
                </div>
            </Modal>
        </slot>
        <Modal :visible="!!files.length" :class="bem('importer')" :showClose="false" top="25%">
            <h3 :class="bem('importer-title')">正在上传图片...</h3>
            <Progress :value="progress" />
            <div slot="footer">
                <Button type="text" @click="cancelUpload">取消</Button>
            </div>
        </Modal>
    </Panel>
</template>

<script>
import Qrcode from '@xkeshi/vue-qrcode';
import Panel from './Panel';
import { createComponentName, componentMixin } from '../_utils/component';
import Upload from '../Upload';
import Button from '../Button';
import Modal from '../Modal';
import Progress from '../Progress';
import Icon from '../Icon';
import tips from '../Tips';
import request from '../request';

// request.post('/api/sessions', { guest_finger: 'guest' });

export default {
    name: createComponentName('editor-upload-panel'),
    components: {
        Panel,
        Icon,
        Modal,
        Upload,
        Qrcode,
        Button,
        Progress,
    },
    mixins: [componentMixin],
    props: {
        // 默认标题
        desc: {
            type: String,
            default: '支持5M以下JPG\\PNG\\GIF格式图片',
        },
        beforeUpload: {
            type: Function,
        },
        accept: {
            type: String,
            default: '',
        }
    },
    data() {
        return {
            status: 'pc', // pc | mobile | qr | url
            qrcode_url: '',
            qrcodeOption: {
                size: 148,
            },
            title: {
                pc: '上传本地图片',
                qr: '上传手机图片',
                mobile: '已连接 \n 请在手机上操作',
            },
            files: [],
            externalImg: '',
            showModal: false,
        };
    },
    computed: {
        progress() {
            return Math.max(this.files.reduce((value, file) => value + file.percent / this.files.length, 0));
        },
    },
    methods: {
        log(error) {
            tips(error);
        },
        toPc() {
            this.status = 'pc';
            this.showModal = false;
        },
        toQr() {
            this.status = 'qr';
            this.generateQrCode();
        },
        handleBeforeUpload(gdFile) {
            if (this.beforeUpload) {
                return this.beforeUpload(gdFile);
            }
            if (gdFile.size > 1024 * 1024 * 5) {
                tips('图片文件过大，最大支持5M');
                return false;
            }

            return gdFile;
        },
        cancelUpload() {
            if (this.$refs.upload) {
                this.$refs.upload.cancelAll();
                this.$refs.upload.clearFiles();
            }
            this.files = [];
        },
        onError(error, file) {
            this.onRemove(file);
            this.log(error);
        },
        onRemove(file) {
            const index = this.files.indexOf(file);
            if (index > -1) {
                this.files.splice(index, 1);
            }
        },
        onChange(files) {
            this.files = files;
        },
        async addElement(src) {
            const { width, height } = await this.getImageSize(src);
            this.$emit('addElement', { type: 'image', url: src, width, height });
        },
        async onUploaded(file) {
            if (this.files.every(f => f.status === 'done')) {
                this.files = [];
                if (this.$refs.upload) this.$refs.upload.clearFiles();
            }
            this.addElement(file.src);
        },
        getImageSize(src) {
            return new Promise((resolve, reject) => {
                const image = new Image();
                image.src = src;
                image.onload = () => {
                    resolve({
                        width: image.width,
                        height: image.height,
                    });
                };

                image.onerror = (error) => reject(error);
            });
        },
        generateQrCode() {
            return request.post('/api/attachments/qrcode_token')
                .then(res => {
                    this.qrcode_url = res.data.url;
                    this.qrcode_token = res.data.token;
                    this.setQrcodeInterval();
                });
        },
        setQrcodeInterval() {
            request.get('/api/qrcodes/' + this.qrcode_token, {
                params: {
                    client_type: 'desktop',
                },
            })
                .then(ret => {
                    if (ret.data.scaned > 0) {
                    // 已被扫描。给二维码设置遮罩、清除状态轮询
                        this.status = 'mobile';
                        this.imgUploadInterval();
                    }
                    if (!ret.data) {
                        this.setQrcodeInterval();
                    }
                })
                .catch((ret) => {
                    if (ret.message === '请求超时，请重试或检查网络状态') {
                        this.setQrcodeInterval();
                    }
                    this.toPc();
                });
        },
        imgUploadInterval() {
            request.get(`/api/attachments/${this.qrcode_token}/images`)
                .then(ret => {
                // 有新的图片上传。执行插入操作.插入完成更新附件状态
                    let retImgs = ret.data;
                    if (retImgs.length > 0) {
                        Promise.all(retImgs.map(item => {
                        /**
                             * 添加元素
                             * @arg elemnt: Elemnt
                             * @Example: this.editor.addImage(element.url);
                             * */
                            this.addElement(item.url);
                            return request.put(`/api/attachments/${item.id}`, {
                                status: 1,
                                qrcode_token: self.qrcode_token,
                            });
                        }))
                            .then(() => {
                                this.imgUploadInterval();
                            })
                            .catch(err => {
                                tips(err);
                            });
                    }
                    else {
                        this.imgUploadInterval();
                    }
                })
                .catch(err => {
                    if (err.message === '请求超时，请重试或检查网络状态') {
                        this.imgUploadInterval();
                    }
                });
        },
        forwardEvent(name, ...args) {
            this.$emit(name, ...args);
        },
        uploadExternalImg() {
            const rImgPath = /^https?:\/\//;
            const errMsg = '无法加载图片，请检查图片地址是否正确';
            const externalImg = this.externalImg.trim();
            if (!rImgPath.test(externalImg)) {
                tips(errMsg);
                return;
            }

            tips.loading('正在加载图片...');
            return request.post('/api/files', {
                url: externalImg,
                type: 'image',
                module: '/design/image',
            })
                .then(res => {
                    tips.close();
                    this.addElement(res.data);
                })
                .catch(() => {
                    tips(errMsg);
                });
        },
    },
};
</script>

<style lang="less">
@import '../_styles/base.less';

@b: ~'@{prefix}-editor-upload-panel';

.@{b} {
    text-align: center;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;

    &__body {
        flex: 1 0 auto;
    }

    &__footer {
        margin-bottom: 30px;
    }

    & &__title {
        font-size: 24px;
        color: #000;
        line-height: 37px;
        margin-bottom: 10px;
        margin-top: 1em;
        padding: 0;
        background: transparent;
        font-family: MicrosoftYaHei;
    }

    &__desc {
        font-size: 12px;
        color: #bbb;
        text-align: center;
    }

    &__upload-btn {
        margin-top: 70px;
        margin-bottom: 24px;
        min-width: 170px;
    }

    &__qrcode {
        margin-top: 44px;
        margin-bottom: 50px;
        width: 148px;
        height: 148px;
    }

    &__qrcode-desc {
        color: #999;
        font-size: 13px;
    }

    &__back-pc {
        margin-top: 30px;
    }

    &__upload-modal {
        text-align: left;

        .@{modal} {
            padding: 23px;
            transition: all .3s ease;
            font-size: 14px;
            line-height: 24px;
            position: absolute;
        }
    }

    &__upload-modal-title {
        font-weight: 700px;
    }

    &__upload-modal-desc {
        color: #dedede;
        margin-bottom: 50px;
    }

    &__upload-modal-url-upload {
        color: #dedede;
        margin-bottom: 50px;
    }

    &__qrcode-scaned {
        display: block;
        margin: auto;
        margin-top: 44px;
    }

    &__url-upload {
        margin-top: 6px;
        display: flex;

        input {
            line-height: 1;
            padding: 0 10px;
            outline: 0;
            height: 36px;
            width: 160px;
            border-radius: 2px;
            border: 1px solid #999;
            color: #ccc;
            background: #000;
            box-sizing: border-box;
        }

        .@{button} {
            border-radius: 2px;
            border: 1px solid #999;
            color: #ccc;
            margin-left: 6px;
            width: 60px;
            height: 36px;
            padding: 0 @margin-sm;
            background: #000;
            box-sizing: border-box;
            background: transparent;
        }
    }

    .@{mask} {
        bottom: 55px;
    }

    &__importer {

        .@{modal} {
            min-width: 900px;
            text-align: center;
        }

        .@{modal}__body {
            margin: 0;
        }

        &-title {
            font-size: 22px;
            font-weight: 400;
            color: #000;
            margin: 0;
        }

        .@{progress} {
            padding-top: 2.286em;
        }

        .@{button} {
            line-height: 84px;
            border: 0;
            color: #005cf9;
            font-size: 16px;
        }
    }
}

.gd-upload-modal-fade-leave-to {
    .@{modal} {
        transform: translate3d(0, 347px, 0);
    }
}
.gd-upload-modal-fade-enter {
    .@{modal} {
        transform: translate3d(0, 347px, 0);
    }
}
</style>
