import pako from 'pako'
import {showloading, hideloading} from '../assets/config/loading';
import {luckysheetrefreshgrid, jfrefreshgrid_rhcw} from '../global/refresh';
import editor from '../global/editor'
import {sheetHTML, luckyColor} from './constant';
import sheetmanage from './sheetmanage';
import menuButton from './menuButton';
import {createFilterOptions} from './filter';
import luckysheetFreezen from './freezen';
import luckysheetPostil from './postil';
import imageCtrl from './imageCtrl';
import dataVerificationCtrl from './dataVerificationCtrl';
import hyperlinkCtrl from './hyperlinkCtrl';
import {getObjType, replaceHtml, getByteLen} from '../utils/util';
import {getSheetIndex} from '../methods/get';
import Store from '../store';
import {collaborativeEditBox} from './select'
import locale from '../locale/locale';
import dayjs from "dayjs";
import json from '../global/json';
import luckysheetConfigsetting from './luckysheetConfigsetting';
import {customImageUpdate} from './imageUpdateCtrl';
import method from '../global/method';
import {getOnlineUser} from "./extFunction";
import { delayMessage } from '../assets/config/loading.js';

const server = {
    gridKey: null,
    loadUrl: null,
    updateUrl: null,
    updateImageUrl: null,
    title: null,
    loadSheetUrl: null,
    retryTimer: null,
    // 文档配置相关操作
    docConfigApi:{
        // 用户登录配置
        loginConfig:{
            // 开启登录校验
            enable: false,
            // 提交表单,#{x} 替换内容
            formData: {
                username: '#{username}',
                password: '#{password}',
            },
            // 返回结果,tokenkey,将获取的值存储在缓存中
            tokenKey: 'access_token',
            // 登录地址
            loginUrl: '',
            // 获取用户信息
            getUserDetail: ''
        },
        // 获取在线用户
        getOnlineUser:'',
        // 详情查询地址
        documentDetailUrl:'',
        // 修改文档标题
        updateDocNameUrl:'',
        // 详情查询地址
        documentHistoryUrl: '',
    },
    // 展示分享按钮
    showShareFlag:true,
    allowUpdate: false, //共享编辑模式
    historyParam: function (data, sheetIndex, range) {
        let _this = this;

        let r1 = range.row[0], r2 = range.row[1];
        let c1 = range.column[0], c2 = range.column[1];

        if (r1 == r2 && c1 == c2) { //单个单元格更新
            let v = data[r1][c1];
            _this.saveParam("v", sheetIndex, v, {"r": r1, "c": c1});
        } else { //范围单元格更新
            let rowlen = r2 - r1 + 1;
            let collen = c2 - c1 + 1;

            let timeR = Math.floor(1000 / collen);
            let n = Math.ceil(rowlen / timeR); //分批次更新,一次最多1000个单元格

            for (let i = 0; i < n; i++) {
                let str = r1 + timeR * i;

                let edr;
                if (i == n - 1) {
                    edr = r2;
                } else {
                    edr = r1 + timeR * (i + 1) - 1;
                }

                let v = [];

                for (let r = str; r <= edr; r++) {
                    let v_row = [];

                    for (let c = c1; c <= c2; c++) {
                        if (data[r] == null) {
                            v_row.push(null);
                        } else {
                            v_row.push(data[r][c]);
                        }
                    }

                    v.push(v_row);
                }

                _this.saveParam("rv", sheetIndex, v, {"range": {"row": [str, edr], "column": [c1, c2]}});

                if (i == n - 1) {
                    _this.saveParam("rv_end", sheetIndex, null);
                }
            }
        }
    },
    saveParam: function (type, index, value, params) {
        let _this = this;

        if (!_this.allowUpdate) {
            return;
        }

        if (value == undefined) {
            value = null;
        }

        let d = {};
        d.t = type;
        d.i = index;
        d.v = value;

        //切换sheet页不发后台,TODO:改为发后台+后台不广播
        if (type === 'shs') {
            return;
        }

        if (type == "rv") { //单元格批量更新
            d.range = params.range;
        } else if (type == "v" || type == "fu" || type == "fm") {
            d.r = params.r;
            d.c = params.c;
        } else if (type == "fc") {
            d.op = params.op;
            d.pos = params.pos;
        } else if (type == "drc" || type == "arc" || type == "h" || type == "wh") {
            d.rc = params.rc;
        } else if (type == "c") {
            d.cid = params.cid;
            d.op = params.op;
        } else if (type == "f") {
            d.op = params.op;
            d.pos = params.pos;
        } else if (type == "s") {

        } else if (type == "sh") {
            d.op = params.op;
            if (params.cur != null) {
                d.cur = params.cur;
            }
        } else if (type == "cg") {
            d.k = params.k;
        } else if (type == "all") {
            d.k = params.k;
            // d.s = params.s;
        }

        // TODO 配置自定义方式同步图片
        const customImageUpdateMethodConfig = luckysheetConfigsetting.imageUpdateMethodConfig
        if (JSON.stringify(customImageUpdateMethodConfig) !== "{}") {
            if ("images" != d.k) {
                let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), {to: "string"});

                if (_this.websocket != null) {
                    _this.websocket.send(msg);
                }
            } else {
                customImageUpdate(customImageUpdateMethodConfig.method, customImageUpdateMethodConfig.url, d)
                    .then((data) => {
                        console.log(data);
                    })
                    .catch((err) => {
                        console.log(err);
                    });

            }
        } else {
            let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), {to: "string"});
            if (_this.websocket != null) {
                _this.websocket.send(msg);
            }
        }

    },
    websocket: null,
    wxErrorCount: 0,
    openWebSocket: function () {
        let _this = this;

        if ('WebSocket' in window) {
            let split = '?';
            if (_this.updateUrl.indexOf('?') > -1) {
                split = '&';
            }
            let wxUrl = _this.updateUrl + split + "t=111&g=" + encodeURIComponent(_this.gridKey);;

            _this.websocket = new WebSocket(wxUrl);

            //连接建立时触发
            _this.websocket.onopen = function () {
                console.info(locale().websocket.success);
                hideloading();
                _this.wxErrorCount = 0;

                //防止websocket长时间不发送消息导致断连
                _this.retryTimer = setInterval(function () {
                    _this.websocket.send("rub");
                }, 60000);
                getOnlineUser();
            }

            //客户端接收服务端数据时触发
            _this.websocket.onmessage = function (result) {
                Store.result = result
                let data = new Function("return " + result.data)();
                method.createHookFunction('cooperativeMessage', data)
                console.info(data);
                let type = data.type;
                let {message, id} = data;
                // 用户退出时,关闭协同编辑时其提示框
                if (message === '用户退出') {
                    $("#luckysheet-multipleRange-show-" + id).hide();
                    Store.cooperativeEdit.changeCollaborationSize = Store.cooperativeEdit.changeCollaborationSize.filter(value => {
                        return value.id != id
                    })
                    Store.cooperativeEdit.checkoutData = Store.cooperativeEdit.checkoutData.filter(value => {
                        return value.id != id
                    })
                }

                delayMessage(data);

                if (type == 0 || type == 999) {
                    // 用户退出或者登录 刷新在线用户
                    getOnlineUser();
                }
                if (type == 1) { //send 成功或失败
                    if(data.data && data.data.v){
                        const oldIndex = data.data.v.index;
                        const sheetToUpdate = Store.luckysheetfile.filter((sheet) => sheet.index === oldIndex)[0];
                        if (sheetToUpdate !== null) {
                            setTimeout(() => {
                                const index = data.data.i;
                                sheetToUpdate.index = index;
                                Store.currentSheetIndex = index;

                                $(`#luckysheet-sheets-item${oldIndex}`).attr('data-index', index);
                                $(`#luckysheet-sheets-item${oldIndex}`).prop('id', `luckysheet-sheets-item${index}`);
                                $(`#luckysheet-datavisual-selection-set-${oldIndex}`).prop('id', `luckysheet-datavisual-selection-set-${index}`);
                            }, 1);
                        }
                    }
                } else if (type == 2) { //更新数据
                    let item = JSON.parse(data.data);
                    _this.wsUpdateMsg(item);
                    let chang_data = JSON.parse(data.data)
                    if (chang_data.k == 'columnlen') {
                        collaborativeEditBox(chang_data.v, null)
                    } else if (chang_data.k == 'rowlen') {
                        collaborativeEditBox(null, chang_data.v)
                    }
                } else if (type == 3) { //多人操作不同选区("t": "mv")(用不同颜色显示其他人所操作的选区)
                    let id = data.id;
                    let username = data.username;
                    let item = JSON.parse(data.data);
                    let type = item.t,
                        index = item.i,
                        value = item.v;
                    if (Store.cooperativeEdit.changeCollaborationSize.length === 0) {
                        Store.cooperativeEdit.changeCollaborationSize.push({id: id, v: item.v[0], i: index})
                    }
                    let flag = Store.cooperativeEdit.changeCollaborationSize.some(value1 => {
                        return value1.id == id
                    })
                    if (flag) {
                        Store.cooperativeEdit.changeCollaborationSize.forEach(val => {
                            if (val.id == id) {
                                val.v = item.v[0] || item.range[0]
                                val.i = index
                            }
                        })
                    } else {
                        Store.cooperativeEdit.changeCollaborationSize.push({id: id, v: item.v[0], i: index})
                    }
                    if (getObjType(value) != "array" && getObjType(value) !== "object") {
                        value = JSON.parse(value);
                    }
                    let r = 0
                    let c = 0
                    if (index == Store.currentSheetIndex) {//发送消息者在当前页面

                        if (getObjType(value) === "object" && value.op === 'enterEdit') {
                            r = value.range[value.range.length - 1].row[0];
                            c = value.range[value.range.length - 1].column[0];
                            _this.multipleRangeShow(id, username, r, c, value.op);

                        } else {

                            r = value[value.length - 1].row[0];
                            c = value[value.length - 1].column[0];

                            _this.multipleRangeShow(id, username, r, c);

                        }

                    } else {
                        if (getObjType(value) === "object" && value.op === 'enterEdit') {
                            r = value.range[value.range.length - 1].row[0];
                            c = value.range[value.range.length - 1].column[0];
                        } else {
                            r = value[value.length - 1].row[0];
                            c = value[value.length - 1].column[0];
                        }
                    }

                    if (Store.cooperativeEdit.checkoutData.length === 0) {
                        if (value.op) {
                            Store.cooperativeEdit.checkoutData.push({id, username, r, c, op: value.op, index})
                        } else {
                            Store.cooperativeEdit.checkoutData.push({id, username, r, c, index})
                        }
                    }
                    let checkoutFlag = Store.cooperativeEdit.checkoutData.some(item => {
                        return item.id == id
                    })
                    if (checkoutFlag) {
                        Store.cooperativeEdit.checkoutData.forEach(item => {
                            if (item.id == id) {
                                item.username = username
                                item.r = r
                                item.c = c
                                item.index = index
                                if (value.op === 'enterEdit') {
                                    item.op = value.op
                                }
                            }
                        })
                    } else {
                        if (value.op === 'enterEdit') {
                            Store.cooperativeEdit.checkoutData.push({id, username, r, c, op: value.op, index})
                        } else {
                            Store.cooperativeEdit.checkoutData.push({id, username, r, c, index})
                        }
                    }

                    //其他客户端切换页面时
                    Store.cooperativeEdit.checkoutData.forEach(item => {
                        if (item.index != Store.currentSheetIndex) {
                            $("#luckysheet-multipleRange-show-" + item.id).hide();
                            item.op == ''
                        }
                    })

                    if ($("#luckysheet-multipleRange-show-" + id)[0]) {
                        let change_bottom = $("#luckysheet-multipleRange-show-" + id)[0].offsetHeight - 1
                        $("#luckysheet-multipleRange-show-" + id + ">.username").css({"bottom": change_bottom + 'px'})
                    }
                } else if (type == 4) { //批量指令更新
                    // let items = JSON.parse(data.data);

                    // After editing by multiple people, data.data may appear as an empty string
                    let items = data.data === "" ? data.data : JSON.parse(data.data);

                    for (let i = 0; i < items.length; i++) {
                        _this.wsUpdateMsg(item[i]);
                    }
                } else if (type == 5) {
                    showloading(data.data);
                } else if (type == 6) {
                    hideloading();
                }
            }

            //通信发生错误时触发
            _this.websocket.onerror = function () {
                _this.wxErrorCount++;

                if (_this.wxErrorCount > 3) {
                    showloading(locale().websocket.refresh);
                } else {
                    showloading(locale().websocket.wait);
                    _this.openWebSocket();
                }
                getOnlineUser();
            }

            //连接关闭时触发
            _this.websocket.onclose = function (e) {
                console.info(locale().websocket.close);
                if (e.code === 1000) {
                    clearInterval(_this.retryTimer)
                    _this.retryTimer = null
                } else {
                    alert(locale().websocket.contact);
                }
                getOnlineUser();
            }
        } else {
            alert(locale().websocket.support);
        }
    },
    wsUpdateMsg: function (item) {
        let type = item.t,
            index = item.i,
            value = item.v;

        let file = Store.luckysheetfile[getSheetIndex(index)];

        if (["v", "rv", "cg", "all", "fc", "drc", "arc", "f", "fsc", "fsr", "sh", "c"].includes(type) && file == null) {
            return;
        }

        if (type == "v") { //单个单元格数据更新
            if (file.data == null || file.data.length == 0) {
                return;
            }

            let r = item.r, c = item.c;
            file.data[r][c] = value;

            if (index == Store.currentSheetIndex) {//更新数据为当前表格数据
                Store.flowdata = file.data;
                editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

                //如果更新的单元格有批注
                if (value != null && value.ps != null) {
                    luckysheetPostil.buildPs(r, c, value.ps);
                } else {
                    luckysheetPostil.buildPs(r, c, null);
                }

                setTimeout(function () {
                    luckysheetrefreshgrid();
                }, 1);
            }
        } else if (type == "rv") { //范围单元格数据更新
            if (Object.keys(item.range).length > 0) {
                Store.cooperativeEdit.merge_range = item.range
                Store.cooperativeEdit.merge_range.v = item.v
                collaborativeEditBox();
            }
            if (file.data == null || file.data.length == 0) {
                return;
            }

            let r1 = item.range.row[0], r2 = item.range.row[1];
            let c1 = item.range.column[0], c2 = item.range.column[1];

            for (let r = r1; r <= r2; r++) {
                for (let c = c1; c <= c2; c++) {
                    file.data[r][c] = value[r - r1][c - c1];
                }
            }

            if (index == Store.currentSheetIndex) {//更新数据为当前表格数据
                Store.flowdata = file.data;
                editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

                //如果更新的单元格有批注
                for (let r = r1; r <= r2; r++) {
                    for (let c = c1; c <= c2; c++) {
                        if (value[r - r1][c - c1] != null && value[r - r1][c - c1].ps != null) {
                            luckysheetPostil.buildPs(r, c, value[r - r1][c - c1].ps);
                        } else {
                            luckysheetPostil.buildPs(r, c, null);
                        }
                    }
                }

                setTimeout(function () {
                    luckysheetrefreshgrid();
                }, 1);
            }
        } else if (type == "cg") { //config更新(rowhidden,rowlen,columnlen,merge,borderInfo)
            let k = item.k;

            if (k == "borderInfo") {
                file["config"]["borderInfo"] = value;
            } else {
                if (!(k in file["config"])) {
                    file["config"][k] = {};
                }

                // for(let key in value){
                //     file["config"][k][key] = value[key];
                // }

                // ⚠️ 上面的处理方式会导致部分配置项被遗漏,以致协同编辑的时候多视图出现不一致的情况,调整处理的策略为直接替换配置项:
                // 可能的配置项为:
                // columnlen: {0: 65, 1: 186, 2: 52}
                // customHeight: {0: 1, 5: 1, 6: 1}
                // customWidth: {0: 1, 1: 1, 2: 1}
                // merge: {2_1: {…}, 4_2: {…}, 6_2: {…}}
                // rowlen: {0: 19, 5: 93, 6: 117}
                if (value && (typeof value == "object")) {
                    file["config"][k] = value;
                }

            }

            if (index == Store.currentSheetIndex) {//更新数据为当前表格数据
                Store.config = file["config"];

                if (k == "rowlen" || k == "columnlen" || k == "rowhidden") {
                    jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
                }

                setTimeout(function () {
                    luckysheetrefreshgrid();
                }, 1);
            }
        } else if (type == "all") { //通用保存更新
            let k = item.k;
            file[k] = value;

            if (k == "name") { //工作表名
                $("#luckysheet-sheet-container-c #luckysheet-sheets-item" + index).find("span.luckysheet-sheets-item-name").html(value);
            } else if (k == "color") { //工作表颜色
                let currentSheetItem = $("#luckysheet-sheet-container-c #luckysheet-sheets-item" + index);
                currentSheetItem.find(".luckysheet-sheets-item-color").remove();

                if (value != null || value != "") {
                    currentSheetItem.append('<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' + value + ';"></div>');
                }
            } else if (k == "pivotTable") { //PivotTable
                // luckysheet.pivotTable.changePivotTable(index);
            } else if (k == "frozen") { //freezen row and column

                // tranform frozen
                luckysheetFreezen.frozenTofreezen();

                if (index == Store.currentSheetIndex) {
                    const _locale = locale();
                    const locale_freezen = _locale.freezen;
                    if (file["freezen"].horizontal == null) {
                        $("#luckysheet-freezen-btn-horizontal").html('<i class="fa fa-list-alt"></i> ' + locale_freezen.freezenRow);
                        luckysheetFreezen.freezenhorizontaldata = null;
                        $("#luckysheet-freezebar-horizontal").hide();
                    } else {
                        luckysheetFreezen.createFreezenHorizontal(file["freezen"].horizontal.freezenhorizontaldata, file["freezen"].horizontal.top);
                    }

                    if (file["freezen"].vertical == null) {
                        $("#luckysheet-freezen-btn-vertical").html('<i class="fa fa-indent"></i> ' + locale_freezen.freezenColumn);
                        luckysheetFreezen.freezenverticaldata = null;
                        $("#luckysheet-freezebar-vertical").hide();
                    } else {
                        luckysheetFreezen.createFreezenVertical(file["freezen"].vertical.freezenverticaldata, file["freezen"].vertical.left);
                    }

                    luckysheetFreezen.createAssistCanvas();
                }
            } else if (k == "filter_select") { //筛选范围
                if (index == Store.currentSheetIndex) {
                    createFilterOptions(value);
                }
            } else if (k == "filter") { //筛选保存
                if (index == Store.currentSheetIndex) {
                    createFilterOptions(file.filter_select, value);
                }
            } else if (k == "luckysheet_conditionformat_save") { //条件格式
                if (index == Store.currentSheetIndex) {
                    setTimeout(function () {
                        luckysheetrefreshgrid();
                    }, 1);
                }
            } else if (k == "luckysheet_alternateformat_save") { //交替颜色
                if (index == Store.currentSheetIndex) {
                    setTimeout(function () {
                        luckysheetrefreshgrid();
                    }, 1);
                }
            } else if (k == "config") { //config
                if (index == Store.currentSheetIndex) {
                    Store.config = value;
                    jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
                }
            } else if (k == "dynamicArray") { //动态数组
                if (index == Store.currentSheetIndex) {
                    setTimeout(function () {
                        luckysheetrefreshgrid();
                    }, 1);
                }
            } else if (k == "images") { //图片
                if (index == Store.currentSheetIndex) {
                    imageCtrl.images = value;
                    imageCtrl.allImagesShow();
                    imageCtrl.init();
                }
            } else if (k == "dataVerification") { //数据验证
                if (index == Store.currentSheetIndex) {
                    dataVerificationCtrl.dataVerification = value;
                    dataVerificationCtrl.init();
                }
            } else if (k == "hyperlink") { //链接
                if (index == Store.currentSheetIndex) {
                    hyperlinkCtrl.hyperlink = value;
                    hyperlinkCtrl.init();
                }
            }
        } else if (type == "fc") { //函数链calc
            let op = item.op, pos = item.pos;

            if (getObjType(value) != "object") {
                value = new Function("return " + value)();
            }

            let r = value.r, c = value.c;

            let calcChain = file["calcChain"] == null ? [] : file["calcChain"];

            if (op == "add") {
                calcChain.push(value);
            } else if (op == "del") {
                for (let a = 0; a < calcChain.length; a++) {
                    if (r == calcChain[a].r && c == calcChain[a].c && index == calcChain[a].index) {
                        calcChain.splice(a, 1);
                    }
                }
            }
            // else if(op == "update"){
            //     for(let a = 0; a < calcChain.length; a++){
            //         if(r == calcChain[a].r && c == calcChain[a].c && index == calcChain[a].index){
            //             calcChain[a].func = func;
            //         }
            //     }
            // }

            setTimeout(function () {
                luckysheetrefreshgrid();
            }, 1);
        } else if (type == "drc") { //删除行列
            if (file.data == null || file.data.length == 0) {
                return;
            }

            let rc = item.rc,
                st_i = value.index,
                len = value.len,
                mc = value.mc,
                borderInfo = value.borderInfo;
            let data = file.data;

            if (rc == "r") {
                file["row"] -= len;

                data.splice(st_i, len);

                //空白行模板
                let row = [];
                for (let c = 0; c < data[0].length; c++) {
                    row.push(null);
                }

                //删除多少行,增加多少行空白行
                for (let r = 0; r < len; r++) {
                    data.push(row);
                }
            } else {
                file["column"] -= len;

                //空白列模板
                let addcol = [];
                for (let r = 0; r < len; r++) {
                    addcol.push(null);
                }

                for (let i = 0; i < data.length; i++) {
                    data[i].splice(st_i, len);

                    data[i] = data[i].concat(addcol);
                }
            }

            for (let x in mc) {
                let r = mc[x].r, c = mc[x].c;
                data[r][c].mc = mc[x];
            }

            file["config"].merge = mc;
            file["config"].borderInfo = borderInfo;

            if (index == Store.currentSheetIndex) {
                Store.flowdata = data;
                editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

                Store.config["merge"] = mc;
                Store.config["borderInfo"] = borderInfo;

                setTimeout(function () {
                    luckysheetrefreshgrid();
                }, 1);
            }
        } else if (type == "arc") { //增加行列
            if (file.data == null || file.data.length == 0) {
                return;
            }

            let rc = item.rc,
                st_i = value.index,
                len = value.len,
                addData = value.data,
                direction = value.direction,
                mc = value.mc,
                borderInfo = value.borderInfo;
            let data = $.extend(true, [], file.data);

            if (rc == "r") {
                file["row"] += len;

                //空行模板
                let row = [];
                for (let c = 0; c < data[0].length; c++) {
                    row.push(null);
                }

                let arr = [];
                for (let i = 0; i < len; i++) {
                    if (addData[i] == null) {
                        arr.push(JSON.stringify(row));
                    } else {
                        arr.push(JSON.stringify(addData[i]));
                    }
                }

                if (direction == "lefttop") {
                    if (st_i == 0) {
                        new Function("data", "return " + 'data.unshift(' + arr.join(",") + ')')(data);
                    } else {
                        new Function("data", "return " + 'data.splice(' + st_i + ', 0, ' + arr.join(",") + ')')(data);
                    }
                } else {
                    new Function("data", "return " + 'data.splice(' + (st_i + 1) + ', 0, ' + arr.join(",") + ')')(data);
                }
            } else {
                file["column"] += len;

                for (let i = 0; i < data.length; i++) {
                    /* 在每一行的指定位置都插入一列 */
                    for (let j = 0; j < len; j++) {
                        if (direction == "lefttop") {
                            data[i].splice(st_i, 0, addData[j]);
                        } else {
                            data[i].splice(st_i + 1, 0, addData[j]);
                        }
                    }
                }
            }

            for (let x in mc) {
                let r = mc[x].r, c = mc[x].c;
                data[r][c].mc = mc[x];
            }

            file.data = data;
            file["config"].merge = mc;
            file["config"].borderInfo = borderInfo;

            if (index == Store.currentSheetIndex) {
                Store.flowdata = data;
                editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据

                Store.config["merge"] = mc;
                Store.config["borderInfo"] = borderInfo;

                setTimeout(function () {
                    luckysheetrefreshgrid();
                }, 1);
            }
        } else if (type == "f") { //筛选
            let op = item.op, pos = item.pos;

            let filter = file.filter;

            if (filter == null) {
                filter = {};
            }

            if (op == "upOrAdd") {
                filter[pos] = value;
            } else if (op == "del") {
                delete filter[pos];
            }

            if (index == Store.currentSheetIndex) {
                createFilterOptions(file.filter_select, filter);
            }
        } else if (type == "fsc") { //清除筛选
            file.filter = null;
            file.filter_select = null;

            if (index == Store.currentSheetIndex) {
                $('#luckysheet-filter-selected-sheet' + Store.currentSheetIndex + ', #luckysheet-filter-options-sheet' + Store.currentSheetIndex).remove();
                $("#luckysheet-filter-menu, #luckysheet-filter-submenu").hide();
            }
        } else if (type == "fsr") { //恢复筛选
            file.filter = value.filter;
            file.filter_select = value.filter_select;

            if (index == Store.currentSheetIndex) {
                createFilterOptions(file.filter_select, file.filter);
            }
        } else if (type == "sha") { //新建sheet
            Store.luckysheetfile.push(value);

            let colorset = '';
            if (value.color != null) {
                colorset = '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' + value.color + ';"></div>';
            }

            $("#luckysheet-sheet-container-c").append(replaceHtml(sheetHTML, {
                "index": value.index,
                "active": "",
                "name": value.name,
                "style": "",
                "colorset": colorset
            }));
            $("#luckysheet-cell-main").append('<div id="luckysheet-datavisual-selection-set-' + value.index + '" class="luckysheet-datavisual-selection-set"></div>');

            // *添加sheet之后,要判断是否需要显示sheet滚动按钮
            sheetmanage.locationSheet()
        } else if (type == "shc") { //复制sheet
            let copyindex = value.copyindex, name = value.name;

            let copyarrindex = getSheetIndex(copyindex);
            let copyjson = $.extend(true, {}, Store.luckysheetfile[copyarrindex]);

            copyjson.index = index;
            copyjson.name = name;

            Store.luckysheetfile.splice(copyarrindex + 1, 0, copyjson);

            let copyobject = $("#luckysheet-sheets-item" + copyindex);
            $("#luckysheet-sheet-container-c").append(replaceHtml(sheetHTML, {
                "index": copyjson.index,
                "active": "",
                "name": copyjson.name,
                "style": "",
                "colorset": ""
            }));
            $("#luckysheet-sheets-item" + copyjson.index).insertAfter(copyobject);
            $("#luckysheet-cell-main").append('<div id="luckysheet-datavisual-selection-set-' + copyjson.index + '" class="luckysheet-datavisual-selection-set"></div>');
        } else if (type == "shd") { //删除sheet
            for (let i = 0; i < Store.luckysheetfile.length; i++) {
                if (Store.luckysheetfile[i].index == value.deleIndex) {

                    // 如果删除的是当前sheet,则切换到前一个sheet页
                    if (Store.currentSheetIndex === value.deleIndex) {
                        const index = value.deleIndex;

                        Store.luckysheetfile[sheetmanage.getSheetIndex(index)].hide = 1;

                        let luckysheetcurrentSheetitem = $("#luckysheet-sheets-item" + index);
                        luckysheetcurrentSheetitem.hide();

                        $("#luckysheet-sheet-area div.luckysheet-sheets-item").removeClass("luckysheet-sheets-item-active");

                        let indicator = luckysheetcurrentSheetitem.nextAll(":visible");
                        if (luckysheetcurrentSheetitem.nextAll(":visible").length > 0) {
                            indicator = indicator.eq(0).data("index");
                        } else {
                            indicator = luckysheetcurrentSheetitem.prevAll(":visible").eq(0).data("index");
                        }
                        $("#luckysheet-sheets-item" + indicator).addClass("luckysheet-sheets-item-active");

                        sheetmanage.changeSheetExec(indicator);
                    }

                    server.sheetDeleSave.push(Store.luckysheetfile[i]);

                    Store.luckysheetfile.splice(i, 1);

                    break;
                }
            }

            $("#luckysheet-sheets-item" + value.deleIndex).remove();
            $("#luckysheet-datavisual-selection-set-" + value.deleIndex).remove();
            sheetmanage.locationSheet()

        } else if (type == "shr") { //sheet位置
            for (let x in value) {
                Store.luckysheetfile[getSheetIndex(x)].order = value[x];
            }
        } else if (type == "shre") { //删除sheet恢复操作
            for (let i = 0; i < server.sheetDeleSave.length; i++) {
                if (server.sheetDeleSave[i].index == value.reIndex) {
                    let datav = server.sheetDeleSave[i];

                    Store.luckysheetfile.push(datav);

                    let colorset = '';
                    if (value.color != null) {
                        colorset = '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' + datav.color + ';"></div>';
                    }

                    $("#luckysheet-sheet-container-c").append(replaceHtml(sheetHTML, {
                        "index": datav.index,
                        "active": "",
                        "name": datav.name,
                        "style": "",
                        "colorset": colorset
                    }));
                    $("#luckysheet-cell-main").append('<div id="luckysheet-datavisual-selection-set-' + datav.index + '" class="luckysheet-datavisual-selection-set"></div>');
                    break;
                }
            }
        } else if (type == "sh") { //隐藏sheet
            let op = item.op, cur = item.cur;

            if (op == "hide") {
                file.hide = 1;
                $("#luckysheet-sheets-item" + index).hide();

                if (index == Store.currentSheetIndex) {
                    $("#luckysheet-sheets-item" + cur).addClass("luckysheet-sheets-item-active");
                    sheetmanage.changeSheetExec(cur);
                }
            } else if (op == "show") {
                file.hide = 0;
                $("#luckysheet-sheets-item" + index).show();
            }
            sheetmanage.locationSheet()
        } else if (type == "c") { //图表操作 TODO
            let op = item.op, cid = item.cid;

            if (op == "add") { //插入
                file.chart.push(value);

                luckysheet.insertChartTosheet(value.sheetIndex, value.dataSheetIndex, value.option, value.chartType, value.selfOption, value.defaultOption, value.row, value.column, value.chart_selection_color, value.chart_id, value.chart_selection_id, value.chartStyle, value.rangeConfigCheck, value.rangeRowCheck, value.rangeColCheck, value.chartMarkConfig, value.chartTitleConfig, value.winWidth, value.winHeight, value.scrollLeft1, value.scrollTop1, value.chartTheme, value.myWidth, value.myHeight, value.myLeft, value.myTop, value.myindexrank1, true);
            } else if (op == "xy" || op == "wh" || op == "update") { //移动 缩放 更新
                for (let i = 0; i < file.chart.length; i++) {
                    let chartjson = file.chart[i];

                    if (chartjson.chart_id == cid) {
                        for (let item in chartjson) {
                            for (let vitem in value) {
                                if (item == vitem) {
                                    chartjson[item] = value[vitem];
                                }
                            }
                        }

                        sheetmanage.saveChart(chartjson);

                        return;
                    }
                }
            } else if (op == "del") { //删除
                for (let i = 0; i < file.chart.length; i++) {
                    let chartjson = file.chart[i];

                    if (chartjson.chart_id == cid) {
                        file.chart.splice(i, 1);

                        $("#" + cid).remove();
                        sheetmanage.delChart($("#" + cid).attr("chart_id"), $("#" + cid).attr("sheetIndex"));

                        return;
                    }
                }
            }
        } else if (type == "na") { //表格名称
            $("#luckysheet_info_detail_input").val(value).css("width", getByteLen(value) * 10);
        }
    },
    multipleIndex: 0,
    multipleRangeShow: function (id, name, r, c, value) {
        let _this = this;
        const fullName = name;

        let row = Store.visibledatarow[r],
            row_pre = r - 1 == -1 ? 0 : Store.visibledatarow[r - 1],
            col = Store.visibledatacolumn[c],
            col_pre = c - 1 == -1 ? 0 : Store.visibledatacolumn[c - 1];

        let margeset = menuButton.mergeborer(Store.flowdata, r, c);
        if (!!margeset) {
            row = margeset.row[1];
            row_pre = margeset.row[0];

            col = margeset.column[1];
            col_pre = margeset.column[0];
        }

        // *处理光标在靠左或者靠上顶着的时候,光标显示不全的问题
        if (col_pre <= 0) {
            col_pre += 1
        }

        if (row_pre <= 0) {
            row_pre += 1
        }

        // 超出16个字符就显示...
        if (getByteLen(name) > 16) {
            name = getByteLen(name, 16) + "...";
        }

        // 如果正在编辑,就显示“正在输入”
        if (value === 'enterEdit') {
            name += " " + locale().edit.typing;
        }

        if ($("#luckysheet-multipleRange-show-" + id).length > 0) {
            $("#luckysheet-multipleRange-show-" + id).css({
                "position": "absolute",
                "left": col_pre - 1,
                "width": col - col_pre - 1,
                "top": row_pre - 1,
                "height": row - row_pre - 1
            });

            $("#luckysheet-multipleRange-show-" + id + " .username").text(name);
            $("#luckysheet-multipleRange-show-" + id + " .username").show();

            if (Store.cooperativeEdit.usernameTimeout['user' + id] != null) {
                clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id])
            }
            Store.cooperativeEdit.usernameTimeout['user' + id] = setTimeout(() => {
                clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id]);
                Store.cooperativeEdit.usernameTimeout['user' + id] = null;
            }, 10 * 1000)


        } else {
            // let itemHtml = '<div id="luckysheet-multipleRange-show-'+ id +'" data-color="'+ luckyColor[_this.multipleIndex] +'" title="'+ name +'" style="position: absolute;left: '+ (col_pre - 1) +'px;width: '+ (col - col_pre - 1) +'px;top: '+ (row_pre - 1) +'px;height: '+ (row - row_pre - 1) +'px;border: 1px solid '+ luckyColor[_this.multipleIndex] +';z-index: 15;">'+
            //                 '<div style="width: 100%;height: 100%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;opacity: 0.03;background-color: '+ luckyColor[_this.multipleIndex] +'"></div>'+
            //                '</div>';

            let itemHtml = `<div
								id="luckysheet-multipleRange-show-${id}"
								class="luckysheet-multipleRange-show"
								data-color="${luckyColor[_this.multipleIndex]}"
								title="${fullName}"
								style="position: absolute;left: ${col_pre - 1}px;width: ${col - col_pre - 1}px;top: ${row_pre - 1}px;height: ${row - row_pre - 1}px;border: 1px solid ${luckyColor[_this.multipleIndex]};z-index: 15;">

								<div class="username" style="height: 19px;line-height:19px;width: max-content;position: absolute;bottom: ${row - row_pre - 1}px;right: 0;background-color: ${luckyColor[_this.multipleIndex]};color:#ffffff;padding:0 10px;">
								${name}
								</div>

								<div style="width: 100%;height: 100%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;opacity: 0.03;background-color: ${luckyColor[_this.multipleIndex]}">
								</div>

							</div>`;
            // 正在输入

            $(itemHtml).appendTo($("#luckysheet-cell-main #luckysheet-multipleRange-show"));

            _this.multipleIndex++;

            // 设定允许用户名消失的定时器,10秒后用户名可隐藏
            // 10秒之类,用户操作界面不会隐藏用户名;10秒之后如果用户操作了界面,则隐藏用户名,没操作就不隐藏
            if (Store.cooperativeEdit.usernameTimeout['user' + id] != null) {
                clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id])
            }
            Store.cooperativeEdit.usernameTimeout['user' + id] = setTimeout(() => {
                clearTimeout(Store.cooperativeEdit.usernameTimeout['user' + id]);
                Store.cooperativeEdit.usernameTimeout['user' + id] = null;
            }, 10 * 1000)
        }
    },
    sheetDeleSave: [], //共享编辑模式下 删除的sheet保存下来,方便恢复时取值
    submitInterval: 1000,
    imagesubmitInterval: 5000,
    submitdatalimit: 50,
    submitcompresslimit: 1000,
    checksubmit: function (data) {
        let _this = this;
        //clearTimeout(_this.requestTimeOut);

        _this.submitTimeout();

        clearTimeout(_this.imageRequestTimeout);
        _this.imageRequestTimeout = setTimeout(function () {
            _this.imageRequest();
        }, _this.imagesubmitInterval);
    },
    submitTimeout: function () {
        let _this = this;
        clearTimeout(_this.requestTimeOut);

        //console.log(_this.requestlast, dayjs(), (_this.requestlast!=null && _this.requestlast.add(10, 'seconds').isBefore(dayjs()) ) );
        if (!_this.requestLock && (_this.requestlast != null && _this.requestlast.clone().add(1, 'seconds').isBefore(dayjs()))) {
            _this.request();
        }

        // if(!_this.imageRequestLock && (_this.imageRequestLast==null || _this.imageRequestLast.clone().add(30, 'seconds').isBefore(dayjs()) ) ){

        // }

        _this.requestTimeOut = setTimeout(function () {
            _this.submitTimeout();
        }, _this.submitInterval);
    },
    requestLock: false,
    requestlast: null,
    firstchange: true,
    requestTimeOut: null,
    request: function () {
        let _this = this;
        let key = this.gridKey;
        let cahce_key = key + "__qkcache";

        _this.cachelocaldata(function (cahce_key, params) {
            if (params.length == 0) {
                return;
            }

            params = encodeURIComponent(JSON.stringify(params));
            let compressBeginLen = params.length;
            let iscommpress = false;
            // if (compressBeginLen > _this.submitcompresslimit) {
            //     params = pako.gzip(params, { to: "string" });
            //     iscommpress = true;
            // }
            _this.requestLock = true;
            //console.log(params);
            // console.log("request");
            if (_this.updateUrl != "") {
                $.post(_this.updateUrl, {compress: iscommpress, gridKey: _this.gridKey, data: params}, function (data) {
                    let re = new Function("return " + data)();
                    if (re.status) {
                        $("#luckysheet_info_detail_update").html("最近存档时间:" + dayjs().format("M-D H:m:s"));
                        $("#luckysheet_info_detail_save").html("同步成功");
                        _this.clearcachelocaldata();
                    } else {
                        $("#luckysheet_info_detail_save").html("<span style='color:#ff2121'>同步失败</span>");
                        _this.restorecachelocaldata();
                    }
                    _this.requestlast = dayjs();
                    _this.requestLock = false;
                });
            }
        });
    },
    imageRequestLast: null,
    imageRequestLock: false,
    imageRequestTimeout: null,
    imageRequest: function () {
        let _this = this;

        html2canvas($("#" + container).find(".luckysheet-grid-window").get(0), {
            onrendered: function (canvas) {
                //let imgcut = $("#luckysheet-cell-main").find(".luckysheet-grid-window");
                //document.body.appendChild(canvas);
                let old = $(canvas).appendTo("body");
                old.hide();
                let newwidth = old.width();
                let newheight = old.height();
                let imageData = old.get(0).getContext("2d").getImageData(0, 0, newwidth, newheight);

                let cutW = newwidth, cutH = newheight;
                if (cutW * 0.54 > cutH) {
                    cutW = cutH / 0.54;
                } else {
                    cutH = cutW * 0.54;
                }
                let newCanvas = $("<canvas>").attr("width", cutW).attr("height", cutH)[0];

                newCanvas.getContext("2d").putImageData(imageData, 0, 0);

                old.attr("width", 350);
                old.attr("height", 189);
                old.get(0).getContext("2d").drawImage(newCanvas, 0, 0, 350, 189);
                let base64 = old.get(0).toDataURL('image/jpeg', 0.9);

                //console.log(base64);
                //console.log("压缩:", pako.gzip(base64, { to: "string" }));
                //console.log("imageRequest");
                let curindex = luckysheet.sheetmanage.getCurSheetnoset();
                _this.imageRequestLock = true;
                // let data1 = pako.gzip(encodeURIComponent(JSON.stringify({"t":"thumb", "img": base64, "curindex":curindex })), { to: "string" });
                let data1 = encodeURIComponent(JSON.stringify({"t": "thumb", "img": base64, "curindex": curindex}));
                old.remove();
                //console.log("缩略图", _this.imageRequestLast,base64);
                if (_this.updateImageUrl != "") {
                    // $.post(_this.updateImageUrl, { compress: true, gridKey: _this.gridKey, data:data1  }, function (data) {
                    $.post(_this.updateImageUrl, {
                        compress: false,
                        gridKey: _this.gridKey,
                        data: data1
                    }, function (data) {
                        let re = new Function("return " + data)();
                        if (re.status) {
                            imageRequestLast = dayjs();
                        } else {
                            $("#luckysheet_info_detail_save").html("<span style='color:#ff2121'>网络不稳定</span>");
                        }
                        _this.imageRequestLock = true;
                    });
                }

            }
        });
    },
    localdata: [],
    matchOpt: function (v, d) {
        for (let vitem in v) {
            if (vitem == "t" && v["t"] in {"drc": 1, "arc": 1, "sha": 1, "shc": 1, "shd": 1}) {
                return false;
            }

            if (vitem == "v") {
                continue;
            }

            if (!(vitem in d)) {
                return false;
            }

            if (d[vitem] != v[vitem]) {
                return false;
            }
        }

        return true;
    },
    deleteRepeatOpt: function (data, value) {
        //let d = $.extend(true, [], data); //原来
        let d = data;
        let _this = this;

        if (value instanceof Array) {
            for (let i = 0; i < value.length; i++) {
                let vitem = value[i];

                for (let a = 0; a < d.length; a++) {
                    let ditem = data[i]; //let ditem = data[a];?

                    if (_this.matchOpt(vitem, ditem)) {
                        delete d[a];
                    }
                }
            }
        } else {
            for (let a = 0; a < d.length; a++) {
                let ditem = d[a];

                if (_this.matchOpt(value, ditem)) {
                    delete d[a];
                }
            }
        }

        let ret = [];
        for (let i = 0; i < d.length; i++) {
            if (d[i] != null) {
                ret.push(d[i]);
            }
        }

        return ret;
    },
    setlocaldata: function (value, func) {
        let key = this.gridKey;
        //store.push(key, data);
        let _this = this;
        _this.getlocaldata(function (data) {
            if (data == null) {
                data = [];
            }

            //此处不去重,在request同步后台时统一循环一次去重
            //let data = _this.deleteRepeatOpt(data, value);

            if (value instanceof Array) {
                data = data.concat(value);
            } else {
                data.push(value);
            }

            _this.localdata = data;
            func(_this.localdata);

            //console.log(value);
            // localforage.setItem(key, data).then(function () {
            //     console.log(data);
            //     func(data);
            // }).catch(function (err) {

            // });
        });
    },
    getlocaldata: function (func) {
        let key = this.gridKey;
        //return store.get(key);
        func(this.localdata);
        // localforage.getItem(key).then(function(readValue) {
        //     func(readValue);
        // });
    },
    clearlocaldata: function (func) {
        let key = this.gridKey;
        //store.remove(key);
        this.localdata = [];
        func();
        // localforage.removeItem(key, function(err,value) {
        //     func();
        // });
    },
    cachelocaldata: function (func) {
        let key = this.gridKey;
        let _this = this;
        let cahce_key = key + "__qkcache";
        //store.remove(key);
        //console.log(key, cahce_key);


        //处理localdata去重
        let updatedata = _this.localdata;
        let uLen = updatedata.length;
        if (uLen > 1) {
            let prevData = [];
            prevData[0] = updatedata[0];
            for (let i = 1; i < uLen; i++) {
                let value = updatedata[i];
                let flag = true;
                for (let a = 0; a < prevData.length; a++) {
                    let ditem = prevData[a];
                    if (_this.matchOpt(value, ditem)) {
                        prevData.splice(a, 1, value);
                        flag = false; //如果已匹配重复,则后续无需再加
                        break;
                    }
                }
                if (flag) {
                    prevData = prevData.concat(value);
                }

            }
            updatedata = prevData;

        }
        if (updatedata == null || updatedata.length == 0) {
            return;
        }
        //console.log(key, cahce_key,updatedata);
        _this.clearlocaldata(function () {
            localforage.setItem(cahce_key, updatedata).then(function () {
                func(cahce_key, updatedata);
            });
        });

        // localforage.getItem(key).then(function(readValue) {
        //     let updatedata = readValue;
        //     if(readValue==null || readValue.length==0){
        //         return;
        //     }
        //     //console.log(key, cahce_key,updatedata);
        //     _this.clearlocaldata(function(){
        //         localforage.setItem(cahce_key, updatedata).then(function () {
        //             func(cahce_key, updatedata);
        //         });
        //     });
        // });
    },
    clearcachelocaldata: function (func) {
        let key = this.gridKey;
        let cahce_key = key + "__qkcache";
        //store.remove(key);
        localforage.removeItem(cahce_key, function (err, value) {
            if (func && typeof (func) == "function") {
                func();
            }

        });
    },
    restorecachelocaldata: function (func) {
        let key = this.gridKey;
        let cahce_key = key + "__qkcache";
        let _this = this;
        localforage.getItem(cahce_key).then(function (readValue) {
            let updatedata = readValue;
            _this.getlocaldata(function (data) {
                if (data == null) {
                    data = [];
                }
                let newdata = updatedata.concat(data);
                //data.unshift(updatedata);

                _this.localdata = newdata;
                if (func instanceof Function) {
                    func(_this.localdata);
                }

                // localforage.setItem(key, newdata).then(function () {
                //     func(newdata);
                // }).catch(function (err) {

                // });
            });
        });
    },
    keepHighLightBox: function () {
        Store.cooperativeEdit.checkoutData.forEach(value => {
            if (value.index == Store.currentSheetIndex) {
                if (value.op === 'enterEdit') {
                    server.multipleRangeShow(value.id, value.username, value.r, value.c, value.op);
                } else {
                    server.multipleRangeShow(value.id, value.username, value.r, value.c);
                }
            }
        })
    }
}

export default server;