import {
    toJS,
    action,
    computed,
    observable,
} from 'mobx';
import {
    FormFactory
} from "../util/formFactory.js";
import {
    mapFormParamsToStyle
} from "../util/paramsToStyle.js";
import {
    getImageInfo
} from "../util/index.js";
import {
    cloneDeep
} from "lodash";
import { WeaLocaleProvider } from "ecCom";
import { message } from "antd"
import * as api from "../apis/index.js";
import { i18n } from '../../../public/i18n.js';
import {addContentPath,UnRe} from '../../../util/index.js'
const getLabel = WeaLocaleProvider.getLabel;


export class BirthEditor {
    constructor(scope) {
        this.staffRemindStore = scope;
    }
    unRe = new UnRe();
    form = null;
    bar_form = null;
    ref = null;
    origin_datas = null;
    //操作对象的类型
    @observable type = "";
    //侧边栏显隐状态值
    @observable visible = false;
    //bar栏是否显示
    @observable is_head_bar_show = true;
    //上传的状态
    @observable uploadStatus = "";
    //上传的文件信息
    @observable uploadList = [];
    //能否撤销
    @observable can_undo = false;
    //能否重做
    @observable can_redo = false;
    //头部数据
    @observable head_bar_datas = {
        form_params: {}
    };
    //背景设置数据
    @observable bg_datas = {
        selectedid: "",
        imgs: [],
        form_params: {},
        isLock: false,
    };
    //图片设置数据
    @observable img_datas = {
        id: "",
        form_params: {},
        isLock: false,
    };
    //卡片头部(标题)设置数据
    @observable head_datas = {
        title: "",
        form_params: {},
        isLock: false,
    }
    //祝词设置数据
    @observable congratulation_datas = {
        paragraph: "",
        form_params: {},
        isLock: false,
    }
    //人员列表设置数据
    @observable person_datas = {
        form_params: {},
        isLock: false,
    }
    //日期设置数据
    @observable date_datas = {
        form_params: {},
        isLock: false,
    }

    //根据type,计算侧边栏所需的属性(部分)
    @computed get slide_props() {
        const type = this.type;

        const slideHeight = {
            "img": 700,
            "bg": 500,
            "head": 795,
            "congratulation": 810,
            "person": 700,
            "date": 590
        }[type]
        
        let height,vHeight = window.innerHeight - 120

       if (slideHeight > vHeight) {
            height = vHeight
       }else{
            height = (slideHeight > 700 ) ? window.innerHeight - 120 :  slideHeight;
       }
        

        const props = {
            top: 100,
            width: 450,
            height,
            direction: "right",
            title: <p className="slide-title">{i18n.label.pictureSet()}</p>
        }

        if (type === "bg") {
            Object.assign(props, {
                direction: "left",
                title: <p className="slide-title">{i18n.label.bgSet()}</p>
            })
        }

        if (type === "head") {
            props.title = <p className="slide-title">{i18n.label.textSet()}</p>
        }

        if (type === "congratulation") {
            props.title = <p className="slide-title" >{i18n.label.congratulationSet()}</p>
        }

        if (type === "person") {
            props.title = <p className="slide-title" >{i18n.label.personListSet()}</p>
        }

        if (type === "date") {
            props.title = <p className="slide-title" >{i18n.label.dateSet()}</p>
        }

        return props;
    }

    //根据type,计算渲染表单所需的数据
    @computed get form_gene_datas() {
        const otherParams = {
            "rich_text": {
                onRef: this.setRef,
                onBlur: this.setTextToCard
            }
        }
        return new FormFactory(this.type, this.handleFormChange, otherParams).compose();
    }

    //卡片是否被选中
    @computed get is_bg_selected() {
        return this.type === "bg";
    }

    //卡片标题是否选中
    @computed get is_head_selected() {
        return this.type === "head";
    }

    //图片是否被选中
    @computed get is_image_selected() {
        return this.type === "img";
    }

    //祝词是否被选中
    @computed get is_congratulation_selected() {
        return this.type === "congratulation";
    }

    //人员信息区域是否被选中
    @computed get is_person_selected() {
        return this.type === "person";
    }

    //日期是否被选中
    @computed get is_date_selected() {
        return this.type === "date";
    }

    //计算卡片背景样式
    @computed get bg_style() {
        const { form_params, selectedid } = this.bg_datas;
        const style = {
            backgroundImage: `url(${this.getImgUrl(selectedid)})`
        }
        Object.assign(style, this.transFormParamsToStyle(form_params))
        return style;
    }

    //计算图片设置中预览图的样式
    @computed get img_preview_style() {
        const style = {
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "250px 80px"
        };

        const { id } = this.img_datas;

        if (id) {
            Object.assign(style, {
                backgroundImage: `url(${this.getImgUrl(id)})`
            })
        };

        return style;
    }

    //卡片上图片的样式
    @computed get body_image_style() {
        const { form_params, id } = this.img_datas;
        const style = {
            backgroundImage: `url(${this.getImgUrl(id)})`
        }
        Object.assign(style, this.transFormParamsToStyle(form_params))
        return style;
    }

    //卡片头部(标题)的样式
    @computed get body_head_style() {
        return this.transFormParamsToStyle(this.head_datas.form_params);
    }

    //祝词的样式
    @computed get body_congratulation_style() {
        return this.transFormParamsToStyle(this.congratulation_datas.form_params);
    }

    //人员信息区域样式
    @computed get body_person_style() {
        return this.transFormParamsToStyle({ ...this.person_datas.form_params, width: 350, height: 210 });
    }

    //日期区域样式
    @computed get body_date_style() {
        return this.transFormParamsToStyle(this.date_datas.form_params);
    }

    //头部(标题)是否显示
    @computed get is_head_show() {
        return (this.type === "head") || this.head_datas.title;
    }

    //祝词是否显示
    @computed get is_congratulation_show() {
        return (this.type === "congratulation") || this.congratulation_datas.paragraph;
    }

    //是否锁定
    @computed get isLock() {
        const datas = this[`${this.type}_datas`];
        return datas && datas.isLock;
    }

    init = () => {
        const fn = (this.staffRemindStore.cardType == "pc") ? "getStaffRemindSettingPc" : "getStaffRemindSettingMobile";
        this[fn]().then(res => {
            this.origin_datas = res;
            this.assginEditorDatas(res);
            this.insertOperation("init");
            this.initCheckGroup()
        })
    }

    initCheckGroup = () => {
        this.setFormFields("head_bar", this.bar_form)
    }

    assginEditorDatas = (datas) => {
        if (datas && (typeof datas === "object") && !Array.isArray(datas)) {
            Object.keys(datas).map(key => {
                if (key === "bg_datas") {
                    this.bg_datas = this.transBgDatas(datas.bg_datas);
                } else {
                    if (key != "date_data") {
                        this[key] = datas[key];
                    } else {
                        this.date_datas = datas[key];
                    }
                }
            })
        }
    }

    transBgDatas = (datas) => {
        datas && datas.imgs.forEach(img => {
            img.src = this.getImgUrl(img.id);
            return img;
        })

        return datas;
    }

    handleBgImgClick = (e) => {
        const {
            id,
            tagName,
        } = e.target;

        if (tagName === "IMG") {
            this.changeBgImgStatus(id);
            return;
        }
        if (id) {
            this.handleBgImgDel(id)
        }
    }

    //改变背景图片的状态
    @action changeBgImgStatus = (id) => {
        const {
            selectedid,
            imgs
        } = this.bg_datas;

        this.bg_datas.selectedid = (id === selectedid) ? "-1" : id;

        this.bg_datas.imgs = imgs.map(img => {
            img.checked = (img.id === this.bg_datas.selectedid) ? true : false;
            return img;
        })
    }

    /**
     * 概述：删除背景图片
     * @param  {[String]} id [图片的id]
     */
    handleBgImgDel = (id) => {
        this.deletePicResource(this.bgImgDelParasm("", id));
    }

    /**
     * 概述：删除除默认图片之外的其他所有图片
     */
    handleBgImgBatchDel = () => {
        this.deletePicResource(this.bgImgDelParasm("batch"));
    }

    bgImgDelParasm = (type, id) => {
        const params = { type: this.staffRemindStore.cardType, scope: "bg" };
        params.imgId = (type == "batch") ? this.getIdsExpectDefaultBgImg() : id;

        const cb = () => {
            this.bgImgCurd(params.imgId, "del");
        }

        return { params, cb }

    }

    /**
     * 概述：删除图片资源
     * @param  {[Object]}   params [接口所需的参数]
     * @param  {Function} cb     [物理删除后执行的回调函数]
     */
    deletePicResource = ({ params, cb }) => {
        api.deletePicResource(params).then(res => {
            const { status } = res;

            if (status == "1") {
                cb && cb();
            } else {
                message.error(res.message);
            }
        })
    }

    /**
     * 概述：保存图片资源
     * @param  {[Object]}   params [接口所需的参数]
     * @param  {Function} cb     [保存成功后执行的回调函数]
     */
    savePicResource = (params, cb) => {
        api.savePicResource(params).then(res => {
            const { status } = res;

            if (status == "1") {
                cb && cb();
            } else {
                message.error(res.message);
            }
        })
    }

    /**
     * 概述：获取生日提醒弹框设置
     */
    getStaffRemindSettingPc = () => {
        return api.getStaffRemindSettingPc().then(res => {
            const { status } = res;
            if (status == "1") {
                this.staffRemindSettingPcInitDatas = this.handleStaffRemindSettingFromAPI(res)
                return res;
            } else {
                message.error(res.message);
            }
        })
    }

    /**
     * 概述：获取生日提醒移动端设置
     */
    getStaffRemindSettingMobile = () => {
        return api.getStaffRemindSettingMobile().then(res => {
            const { status } = res;
            if (status == "1") {
                return res;
            } else {
                message.error(res.message);
            }
        });
    }

    /**
     * 概述：背景图片的增删(不走接口，改变的是状态值)
     * @param  {[String]} ids [图片的id]
     * @param  {[String]} type [操作的类型]
     */
    bgImgCurd = (ids, type) => {
        const str = (typeof ids != "string") ? ids.toString() : ids,
            arr = str.split(","),
            imgs = this.bg_datas.imgs;

        if (type == "add") {
            arr.forEach(id => {
                imgs.push({
                    id,
                    checked: false,
                    src: this.getImgUrl(id)
                });
            })
        }
        if (type == "del") {
            arr.forEach(id => {
                const targetIndex = imgs.findIndex(img => img.id == id);

                if (targetIndex != -1) {
                    imgs.splice(targetIndex, 1);
                }
            })
        }
    }

    //初始化表单
    initFormField = () => {
        this.setFormFields();
    }

    setFormFields = (type, form) => {
        const __type = type || this.type;
        const __form = form || this.form;
        const form_params = this[`${__type}_datas`].form_params;
        const fields = this.transformParams(form_params);
        __form && __form.setFields(fields);
    }

    getImgUrl = (id) => {
        if (id === "0") {
            if (this.staffRemindStore.cardType == "pc") {
                return  addContentPath(this.bgDefaultImg || "/images_face/ecologyFace_1/BirthdayFace/1/BirthdayBg_3_wev8.jpg");
            }
            return addContentPath("/hrm/hrm_e9/image/u59.png") ;
        } else {
            return addContentPath(`/weaver/weaver.file.FileDownload?fileid=${id}`);
        }
    }

    getIdsExpectDefaultBgImg = () => {
        return this.bg_datas.imgs.filter(img => img.id != "0").map(img => img.id).toString();
    }

    //将form_params转换成setFormFields所需的参数
    transformParams = (datas) => {
        const obj = {};
        Object.keys(datas).forEach(key => {
            Object.assign(obj, {
                [key]: {
                    value: datas[key]
                }
            });
        });
        return obj;
    }

    //将表单参数转换成HTML元素所需的样式
    transFormParamsToStyle = (params) => {
        const style = {};
        const { cardType } = this.staffRemindStore;
        const cloneParams = cloneDeep(params);
        (typeof cloneParams === "object") && Object.keys(cloneParams).map(key => {
            const val = cloneParams[key];
            cloneParams.card_width = (cardType == "pc") ? 500 : 400;
            cloneParams.card_height = (cardType == "pc") ? 475 : 644;
            Object.assign(style, mapFormParamsToStyle(key, val, cloneParams));
        })

        return style;
    }


    //实现旋转、不透明度滑动条和输入框之间的双向数据绑定
    @action handleFormChange = (key, val) => {
        const params = {
            rotate: { "rotate-num": val, rotate: val },
            "rotate-num": { "rotate-num": val, rotate: val },
            transparency: { "transparency-num": val, transparency: val },
            "transparency-num": { "transparency-num": val, transparency: val },
        };

        if (this.type == "img" && this.img_datas.id && val) {
            params.width = { width: val, height: (val * this.imgRatio).toFixed(2) };
            params.height = { width: (val * (1 / this.imgRatio)).toFixed(2), height: val }
        }

        const fn_name = `set${this.type.replace(/\b\w/, c => c.toUpperCase())}FormParams`;
        if (params[key]) {
            this[fn_name](params[key]);
            this.setFormFields();
        }
        //操作表单，触发handleFormChange回调函数，然后触发组件的componentDidUpdate方法更新表单参数
        //假如insertOperation不用setTimeout包裹，按照执行顺序会依次执行: handleFormChange -> insertOperation ->componentDidUpdate
        //这样就会导致插入到undoRedo对象中的表单数据不是最新的，而是上一个动作的数据。
        setTimeout(() => {
            this.insertOperation();
        }, 0)

    }

    @action handleUploadChange = (ids, list, type) => {
        this.uploadList = list;
        const { cardType } = this.staffRemindStore;
        if (list.length > 0) {
            //上传背景图
            if (type === "1") {
                const ids = list.filter(item => item.fileidCode != void 0).map(item => item.fileidCode);

                const params = {
                    imgId: ids.join(","),
                    type: cardType,
                    scope: "bg"
                };

                const cb = () => {
                    this.bg_datas.imgs = [...this.bg_datas.imgs, ...ids.map(id => ({
                        id,
                        checked: false,
                        src: this.getImgUrl(id)
                    }))]
                };

                this.savePicResource(params, cb);
            } else { //更新图片(背景图上面的图片)
                const fileid = list[0].fileidCode;
                this.setImgId(fileid.toString());
                this.recoveOriginImg();
            }
        }
    }

    @action setTextToCard = () => {
        const text = this.rich_ref && this.rich_ref.getData();
        if (["head", "congratulation"].includes(this.type)) {
            (this.type === "head") ? this.setHeadTitle(text) : this.setCongratulationPara(text);
        }
    }

    @action handleUploadStatus = (status) => {
        this.uploadStatus = status;
    }

    //卡片元素点击事件回调
    @action handleCardItemClick = (e, type) => {
        e.stopPropagation();

        if (type != this.type) this.setVisible(false);
        this.setType(type);
        !this.isLock && this.setVisible(true);
    }

    @action toggle = () => {
        const type = this.type;
        const datas = this[`${type}_datas`];
        if (datas) {
            const isLock = datas.isLock;
            this[`${type}_datas`].isLock = !isLock;
            this.setVisible(isLock);
        }
    }

    handleUndoRedoClick = (key) => {
        this[key]();
    }

    handleHeadButtonClick = (key) => {
        this[key]();
    }

    save = () => {
        const params = {};
        const dataProps = ["bg_datas", "img_datas", "head_datas", "congratulation_datas", "person_datas", "date_datas", "head_bar_datas"];
        for (let index = 0; index < dataProps.length; index++) {
            const v = dataProps[index]

            // if (v == 'congratulation_datas' && this[v].paragraph.length > 500) {
            //     message.warning(i18n.label.congratulationLengthWarning())
            //     return
            // }

            const datas = this.handleStaffRemindSetting(v);

            Object.assign(params, {
                [v]: JSON.stringify(datas)
            });

        }
        const { cardType } = this.staffRemindStore;
        api[(cardType == "pc") ? "savePcStaffRemindSetting" : "saveMobileStaffRemindSetting"](params).then(res => {
            if (res.status == "1")
                message.success(getLabel(83551, '保存成功！'))
            else
                message.warning(res.message);
        })
    }

    //预览
    preview = () => {
        this.setHeadBarStatus(false);
        this.setVisible(false);
    }

    //恢复默认
    restoreDefault = () => {
        api.resetSetting({ type: this.staffRemindStore.cardType }).then(res => {
            if (res.status == "1") {
                this.origin_datas = res;
                this.assginEditorDatas(res);
                this.initCheckGroup();
                this.unRe.clear();
                this.insertOperation("init");
                this.can_undo = false;
                this.can_redo = false;
            } else {
                message.error(res.message);
            }
        })
    }

    //撤销
    undo = () => {
        if (this.can_undo) {
            this.unRe.undo();
            this.recover(this.unRe.peek());
        }
    }

    //重做
    redo = () => {
        if (this.can_redo) {
           this.unRe.redo();
           this.recover(this.unRe.peek());
        }
    }

    recover = (operation) => {
        Object.keys(operation).forEach(key => {
            if (this[key]) {
                this[key] = operation[key];
            }
        })
        //变量form和type存在，说明侧边栏是开启的状态，这个时候需要调用setFormFields去更新表单的状态
        //假如侧边栏是关闭的状态，则不需要这样做，因为重新打开侧边栏时，会自动调用setFormFields
        if (this.form && this.type) {
            this.setFormFields();
        }
        //setFormFields依赖与当前的form对象。假如在侧边栏开启的情况下，同时操作了bar栏的表单元素，
        //这个时候需要往setFormFields传入参数，再执行一次。
        if (this.bar_form) {
            this.setFormFields("head_bar", this.bar_form);
        }

        this.can_undo = this.unRe.canUn();
        this.can_redo = this.unRe.canRe();
    }

    insertOperation = (type) => {
        const __type = type || this.type;
        //页面初始化时，需要往undoRedo对象中插入原始数据
        if (__type === "init") {
            this.unRe.insert(this.staffRemindSettingPcInitDatas);
        } else {
            const datas = {};
            [
                "head_bar_datas",
                "bg_datas",
                "img_datas",
                "head_datas",
                "congratulation_datas",
                "person_datas",
                "date_datas",
            ].forEach(key => {
                if (this[key]) {
                    //必须使用cloneDeep对数据进行深拷贝，避免下一个动作的数据影响上一个。
                    Object.assign(datas, {
                        [key]: cloneDeep(toJS(this[key]))
                    })
                }
            })
            this.unRe.insert(datas)
        }
        this.can_undo = this.unRe.canUn();
        this.can_redo = this.unRe.canRe();
    }

    handleKeyDown = (e) => {
        const {
            ctrlKey,
            which
        } = e;

        if (ctrlKey) {
            (which === 26) && this.undo();
            (which === 25) && this.redo();
        }
    }

    handleBottomBarClick = (index) => {
        switch (index) {
            case 0:
                this.upperElement();
                break;
            case 1:
                this.upperElement();
                break;
            case 2:
                this.downElement();
                break;
            case 3:
                this.downElement();
                break;
            case 4:
                this.deleteElement()
                break;

            default:
                break;
        }
        this.insertOperation()
    }

    recoveOriginImg = () => {
        const { id } = this.img_datas;
        const url = id ? this.getImgUrl(id) : "";

        if (url) {
            getImageInfo(url, (width, height) => {
                const params = { width, height };
                this.imgRatio = height / width;
                this.setImgFormParams(params);
                this.setFormFields();
                this.insertOperation();
            })
        }
    }

    @action setType = (type) => {
        this.type = type;
    }

    @action setVisible = (bool) => {
        this.visible = bool;
    }

    @action setBgImgs = (imgs) => {
        this.bg_datas.imgs = imgs;
    }

    @action setBgFormParams = (params) => {
        this.bg_datas.form_params = params;
    }

    @action setImgId = (id) => {
        this.img_datas.id = id;
    }

    @action setImgFormParams = (params) => {
        Object.assign(this.img_datas.form_params, params);
    }

    @action setHeadFormParams = (params) => {
        Object.assign(this.head_datas.form_params, params);
    }

    @action setHeadTitle = (title) => {
        this.head_datas.title = title;
    }

    @action setCongratulationPara = (paragraph) => {
        this.congratulation_datas.paragraph = paragraph;
    }

    @action setCongratulationFormParams = (params) => {
        this.congratulation_datas.form_params = params;
    }

    @action setPersonFormParams = (params) => {
        this.person_datas.form_params = params;
    }

    @action setDateFormParams = (params) => {
        this.date_datas.form_params = params;
    }

    @action setHeadFieldsParams = (params) => {
        this.head_bar_datas.form_params = params;
    }

    @action setHeadBarStatus = (bool) => {
        this.is_head_bar_show = bool;
    }

    setForm = (form) => {
        this.form = form;
    }

    setBarForm = (form) => {
        this.bar_form = form;
    }

    setRef = (ref) => {
        this.rich_ref = ref;
        this.time = setTimeout(() => {
            if (ref.getData()) {
                clearTimeout(this.time)
            } else {
                ref.setData(this.type == "head" ? this.head_datas.title : this.congratulation_datas.paragraph);
            }
        }, 500)
    }

    setTextFormParams = (params) => {
        (this.type === "head") ? this.setHeadFormParams(params) : this.setCongratulationFormParams(params);
    }


    upperElement() {
        const domMap = this.getDomMap();
        $(`.${domMap[this.type]}`).css('display', 'block');
    }

    downElement = () => {
        const domMap = this.getDomMap();
        $(`.${domMap[this.type]}`).css('display', 'none');
    }

    deleteElement = () => {
        switch (this.type) {
            case 'img':
                this.setImgId('');
                break;
            case 'head':
            case 'congratulation':
                this.rich_ref.setData('');
                break;
            case 'person':
                this.bar_form.setFieldsValue({fields:  ['1'] })
            case 'date':
                this.bar_form.setFieldsValue({content:  ['1'] })
            default:
                break;
        }
    }

    getDomMap() {
        return {
            img: 'editor-body-img',
            head: 'editor-body-head',
            congratulation: 'editor-body-congratulation',
            person: 'editor-body-person',
            date: 'editor-body-date',
        };
    }

    handleStaffRemindSetting(v) {
        const formParams = this[v]['form_params'] && cloneDeep(toJS(this[v]['form_params']));
        if (formParams) {
            ['font-color', 'bg-color'].forEach(field => {
                if (formParams[field] && formParams[field] == 'transparent') {
                    formParams[field] = '';
                }
            });
        }

        const datas = Object.assign({}, this[v]);

        if (formParams) {
            Object.assign(datas, { 'form_params': formParams });
        }
        return datas;
    }

    handleStaffRemindSettingFromAPI = (res) => {
        for (let key in res) {
            if (res.hasOwnProperty(key)) {
                const value = res[key]
                if (typeof value == 'object') {
                    this.handleStaffRemindSettingFromAPI(value)
                } else {
                    if ((key == 'font-color' && value === '') || (key == 'bg-color' && value === '')) {
                        res[key] = 'transparent'
                    }
                }
            }
        }
        return res;
    }
}