/**
 * 项目工料机相关spread
 *
 * @author CaiAoLin
 * @date 2017/7/19
 * @version
 */

/**
 * 构造函数
 *
 * @return {void}
 */
function ProjectGLJSpread() {
    this.isChanging = false;
    this.sheetObj = null;
    this.firstMachineRow = -1;
    this.firstMixRatioRow = -1;
    this.successCallback = null;
    this.supplyType = ['自行采购', '部分甲供', '完全甲供', '甲定乙供'];
    this.supplyComboMap = supplyComboMap
    // 工料机类型是混凝土、砂浆、配合比、机械(不包括机械组成物)时，供货方式列只读。
    this.supplyReadonlyType = gljUtil.notEditType;
}

/**
 * 初始化
 *
 * @return {object}
 */
ProjectGLJSpread.prototype.init = function () {
    // 供货方式类型
    let supplySelect = [];
    for(let comM of this.supplyComboMap) {
        supplySelect.push({
            text: comM.text,
            value: comM.value
        });
    }
    let selectBox = new GC.Spread.Sheets.CellTypes.ComboBox();
    selectBox.items(supplySelect);
    selectBox.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.value);
    let header = [
        {name: '编码', field: 'code', visible: true,width:80},
        {name: '名称', field: 'name', visible: true,width:160},
        {name: '规格型号', field: 'specs', visible: true,width:120},
        {name: '单位', field: 'unit', visible: true,width:45},
        {name: '类型', field: 'short_name', visible: true,width:45},
        {name: '类型', field: 'unit_price.type', visible: false},
        {name: '总消耗量', field: 'quantity', visible: true,width:100,decimalField:'glj.quantity'},
        {name: '定额价', field: "base_price", visible: true,width:70,decimalField:"glj.unitPrice",validator: 'number'},//这里feiedID设置是为了在计不计取价差的时候做显示用
        {name: '调整价', field: 'adjust_price', visible: true,width:70,decimalField:"glj.unitPrice"},
        {name: '市场价', field: "unit_price.market_price", visible: true, validator: 'number',width:70,decimalField:"glj.unitPrice"},
        {
            name: '是否暂估',
            field: 'is_evaluate',
            visible: true,
            cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),
            validator: 'boolean'
            ,width:60
        },
        {name: '供货方式', field: 'supply', visible: true, cellType: selectBox,width:80},
        {name: '甲供数量', field: 'supply_quantity',validator:'number', visible: true,width:100},
        {name: '交货方式', field: 'delivery', visible: true,width:90},
        {name: '送达地点', field: 'delivery_address', visible: true,width:100},
        {
            name: '不调价',
            field: 'is_adjust_price',
            visible: true,
            cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),
            validator: 'boolean',
            width:55
        },
        {name: 'UID', field: 'unit_price.id', visible: false},
        {name: '工料机ID', field: 'glj_id', visible: false},
        {name: '组成物消耗量', field: 'consumption', visible: false},
        {name: '父级关联编码', field: 'connect_code', visible: false},
        {name: '组成物信息', field: 'ratio_data', visible: false},
        {name: '分部分项总消耗量', field: 'subdivisionQuantity', visible: false,width:100,decimalField:'glj.quantity'},
        {name: '技术措施项目总消耗量', field: 'techQuantity', visible: false,width:100,decimalField:'glj.quantity'},
        {name: 'ID', field: 'id', visible: false}
    ];
    let sourceData = jsonData;

    this.sheetObj = new CommonSpreadJs(header);
    this.sheetObj.init('project-glj');

    // 获取列号
    let isEvaluateColumn = this.sheetObj.getFieldColumn('is_evaluate');
    let isAdjustPriceColumn = this.sheetObj.getFieldColumn('is_adjust_price');
    let unitColumn = this.sheetObj.getFieldColumn('unit');
    let quantityColumn = this.sheetObj.getFieldColumn('quantity');
    let basePriceColumn = this.sheetObj.getFieldColumn('base_price');
    let adjustPriceColumn = this.sheetObj.getFieldColumn('adjust_price');
    let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
    let supplyColumn = this.sheetObj.getFieldColumn('supply');
    let shortNameColumn = this.sheetObj.getFieldColumn('unit_price.short_name');
    let supplyQuantity = this.sheetObj.getFieldColumn('supply_quantity');
    let nameColumn = this.sheetObj.getFieldColumn('name');
    let specsColumn = this.sheetObj.getFieldColumn('specs');

    //左对齐样式
    let leftStyleSetting = {hAlign: GC.Spread.Sheets.HorizontalAlign.left};
    this.sheetObj.setStyle(-1, nameColumn, leftStyleSetting);
    this.sheetObj.setStyle(-1, specsColumn, leftStyleSetting);

    // 居中样式
    let centerStyleSetting = {hAlign: 1};
    this.sheetObj.setStyle(-1, isEvaluateColumn, centerStyleSetting);
    this.sheetObj.setStyle(-1, isAdjustPriceColumn, centerStyleSetting);
    this.sheetObj.setStyle(-1, unitColumn, centerStyleSetting);
    this.sheetObj.setStyle(-1, shortNameColumn, centerStyleSetting);

    // 向右对齐样式
    let rightStyleSetting = {hAlign: GC.Spread.Sheets.HorizontalAlign.right};
    this.sheetObj.setStyle(-1, quantityColumn, rightStyleSetting);
    this.sheetObj.setStyle(-1, basePriceColumn, rightStyleSetting);
    this.sheetObj.setStyle(-1, adjustPriceColumn, rightStyleSetting);
    this.sheetObj.setStyle(-1, marketPriceColumn, rightStyleSetting);
    this.sheetObj.setStyle(-1, supplyColumn, rightStyleSetting);
    this.sheetObj.setStyle(-1, supplyQuantity, rightStyleSetting);

    // 设置可编辑列
    this.sheetObj.setColumnEditable(basePriceColumn);
    this.sheetObj.setColumnEditable(marketPriceColumn);
    this.sheetObj.setColumnEditable(isEvaluateColumn);
    this.sheetObj.setColumnEditable(isAdjustPriceColumn);
    this.sheetObj.setColumnEditable(supplyColumn);
    this.sheetObj.setData(sourceData);
    // 取消正在加载字符提示
    $("#project-glj > p").hide();
    this.specialColumn(sourceData);

    // 绑定修改事件
    let self = this;
    this.sheetObj.bind(GC.Spread.Sheets.Events.ValueChanged, function(element, info) {
        self.updateProjectGLJField(info, self.successCallback);
    });

    // 绑定双击事件
    this.sheetObj.bind(GC.Spread.Sheets.Events.CellDoubleClick, function (element, info) {
        let column = info.col;
        let row = info.row;
        let field = self.sheetObj.getColumnField(column);
        let activeSheet = self.sheetObj.getSheet();

        // 获取类型
        let typeColumn = self.sheetObj.getFieldColumn('unit_price.type');
        let type = activeSheet.getValue(row, typeColumn);

        let ratioColumn = self.sheetObj.getFieldColumn('ratio_data');
        let ratioData = activeSheet.getValue(row, ratioColumn);

        // 如果类型为混凝土、砂浆、配合比、机械，则提示
        if (field === 'unit_price.market_price' && canNotChangeTypeId.indexOf(type) >= 0) {
            if(ratioData&&ratioData.length>0){
                alert('当前工料机的市场单价由组成物计算得出，不可直接修改');
            }
        }
    });


    return this.sheetObj;
};

/**
 * 更新项目工料机中的数据字段
 *
 * @param {object} info
 * @param {function} callback
 * @return {void|boolean}
 */
ProjectGLJSpread.prototype.updateProjectGLJField = function(info, callback) {
    // 获取修改的数据
    let column = info.col;
    let row = info.row;
    let idString = 'id';
    let field = projectGLJSheet.getColumnField(column);

    if (field === '') {
        return false;
    }
    let activeSheet = projectGLJSheet.getSheet();

    // 切割字段
    let fieldArray = field.split('.');
    idString = fieldArray.length > 1 ? 'unit_price.id' : idString;

    // 防止快速同时提交
    if (isChanging) {
        return false;
    }

    // 校验数据
    let value = info.newValue;
    if (!projectGLJSheet.checkData(column, value)) {
        alert('输入的数据类型不对，请重新输入!');
        activeSheet.setValue(row, column, info.oldValue);
        return false;
    }

    // 获取id
    let idColumn = projectGLJSheet.getFieldColumn(idString);
    if (idColumn < 0) {
        return false;
    }
    let id = activeSheet.getValue(row, idColumn);

    // 直接在前端计算后传值后台改
    let extend = {};
/*    let updateRecord = jsonData[row];  这时修改成在后端计算后直接更新，因为还要重新计算受影响的清单节点
    let parentMarketPrice = projectGLJSpread.compositionCalculate(updateRecord);
    if (parentMarketPrice !== null && Object.keys(parentMarketPrice).length > 0) {
        for (let activeCode in parentMarketPrice) {
            let tmpObject = {
                market_price: parentMarketPrice[activeCode],
            };
            extend[activeCode] = tmpObject;
        }
    }*/

    // 如果是供货方式则需要处理数据
    if (field === 'supply') {
        // value = this.supplyType.indexOf(value);
        extend.supply_quantity = this.getSupplyQuantity(value, activeSheet, info);
    }
    if(field === 'supply_quantity'){//修改数量需做4舍5入
        value= value.toDecimal(getDecimal('glj.quantity'));
    }
    if(field === 'unit_price.market_price'||field === 'base_price'){
        value= scMathUtil.roundForObj(value,getDecimal('glj.unitPrice'));//修改市场价和修改定额价时需要重新记算很多受影响的树节点，现在改成与定字额工料机那里调相同的方法。
        let editField = field === 'base_price'?field:"market_price";
        projectObj.project.projectGLJ.updatePrice(jsonData[row],editField,value);
        return;
    }
    extend = Object.keys(extend).length > 0 ?  JSON.stringify(extend) : '';
    this.postUpdate(id,field,value,info,extend,callback);
};

ProjectGLJSpread.prototype.postUpdate=function (id,field,value,info,extend,callback) {
    $.bootstrapLoading.start();
    $.ajax({
        url: '/glj/update',
        type: 'post',
        data: {id: id, field: field, value: value, extend: extend},
        dataType: 'json',
        error: function(jqXHR, textStatus, errorThrown) {
            ajaxErrorInfo(jqXHR, textStatus, errorThrown);
            isChanging = false;
        },
        beforeSend: function() {
            isChanging = true;
        },
        success: function(response) {
            isChanging = false;
            // 修改失败则恢复原值
            if (response.err !== 0&&info.fromRG!=true) {
                projectGLJSheet.getSheet().setValue(info.row, info.col, info.oldValue);
                alert('更改数据失败!');
            } else {
                // 成功则触发相应事件
                /* if (parentMarketPrice !== null) {
                 info.parentMarketPrice = parentMarketPrice;
                 }*/
                if(field !== 'supply'&&info.fromRG!=true){ //供货方式需做转换才能直接设置值， 这里设置值是为了早点更新数据，等getdata返回数据再刷新的话会有比较大的延时
                    projectGLJSheet.getSheet().setValue(info.row, info.col, value);
                }
                callback(field, info,id);
            }
        }
    });


}


/**
 * 设置特殊单元格数据
 *
 * @param {object} sourceData
 * @return {void}
 */
ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
    let rowCounter = 0;
    // 获取列号
    let isEvaluateColumn = this.sheetObj.getFieldColumn('is_evaluate');
    let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
    let basePriceColumn = this.sheetObj.getFieldColumn('base_price');
    let adjustPriceColumn = this.sheetObj.getFieldColumn("adjust_price");
    let connectCodeColumn = this.sheetObj.getFieldColumn('connect_code');
    let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
    let supplyColumn = this.sheetObj.getFieldColumn('supply');
    let shortNameColumn = this.sheetObj.getFieldColumn('short_name');
    let supplyQuantity = this.sheetObj.getFieldColumn('supply_quantity');
    let activeSheet = this.sheetObj.getSheet();

    for (let data of sourceData) {
        let rowStyle = null;
        //设置类型名称：
        activeSheet.setValue(rowCounter, shortNameColumn,projectObj.project.projectGLJ.getShortNameByID(data.unit_price.type));
        // 只有材料才显示是否暂估
        if (materialIdList.indexOf(data.unit_price.type) < 0) {
            let string = new GC.Spread.Sheets.CellTypes.Text();
            activeSheet.setCellType(rowCounter, isEvaluateColumn, string, GC.Spread.Sheets.SheetArea.viewport);

            // 锁定该单元格
            activeSheet.getCell(rowCounter, isEvaluateColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
            activeSheet.setValue(rowCounter, isEvaluateColumn, '');
        }else {
            let checkBox = new GC.Spread.Sheets.CellTypes.CheckBox();
            activeSheet.setCellType(rowCounter, isEvaluateColumn, checkBox, GC.Spread.Sheets.SheetArea.viewport);
            activeSheet.getCell(rowCounter, isEvaluateColumn, GC.Spread.Sheets.SheetArea.viewport).locked(false);
            activeSheet.setValue(rowCounter, isEvaluateColumn, data.is_evaluate);
        }
       /* // 设置供货方式列是否可选
        if (this.supplyReadonlyType.indexOf(data.unit_price.type) >= 0) {
            // 锁定该单元格
            activeSheet.getCell(rowCounter, supplyColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
        }*/
        // 如果为部分甲供则甲供数量需要可编辑
        if (data.supply == 1) {
            activeSheet.getCell(rowCounter, supplyQuantity,  GC.Spread.Sheets.SheetArea.viewport).locked(false);
        }
        //供货方式为完全甲供时设置甲供数量为总消耗量
        if (data.supply == 2) {
            activeSheet.setValue(rowCounter, supplyQuantity,  data.quantity);
        }
        // 供货方式数据
        let supplyIndex = parseInt(data.supply);
        supplyIndex = isNaN(supplyIndex) ? 0 : supplyIndex;
        let supplyText = this.supplyType[supplyIndex] !== undefined ? this.supplyType[supplyIndex] : '自行采购';
        activeSheet.setValue(rowCounter, supplyColumn, supplyText);
        // activeSheet.setValue(rowCounter, supplyColumn, supplyIndex);

        // 如果类型为混凝土、砂浆、配合比、机械，则市场单价和供货方式不能修改
        if (canNotChangeTypeId.indexOf(data.unit_price.type) >= 0) {
            this.firstMixRatioRow = this.firstMixRatioRow === -1 && data.unit_price.type !== GLJTypeConst.GENERAL_MACHINE ?
                rowCounter : this.firstMixRatioRow;
            this.firstMachineRow = this.firstMachineRow === -1 && data.unit_price.type === GLJTypeConst.GENERAL_MACHINE ?
                rowCounter : this.firstMachineRow;
            // 锁定该单元格
            if (data.ratio_data  && data.ratio_data.length > 0){//有组成物时，市场单价、定额价、供货方式不能修改
                activeSheet.getCell(rowCounter, marketPriceColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
                activeSheet.getCell(rowCounter, basePriceColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
                activeSheet.getCell(rowCounter, supplyColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
                //设置底色
                rowStyle = this.getRowStyle("#E0E0E0");
            }
        }
        if(data.unit_price.is_add!=1){//如果不是新增，定额价不可修改。
            activeSheet.getCell(rowCounter, basePriceColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
        }

        // 处理数据
        if (data.ratio_data !== undefined && data.ratio_data.length > 0) {
            let connectCode = [];
            let consumption = [];
            for (let tmp of data.ratio_data) {
                connectCode.push(tmp.connect_key);
                consumption.push(tmp.consumption);
            }
            let connectCodeString = connectCode.join(',');
            let consumptionString = consumption.join(',');
            activeSheet.setValue(rowCounter, connectCodeColumn, connectCodeString);
            activeSheet.setValue(rowCounter, consumptionColumn, consumptionString);
        }
        data=this.sheetObj.setProjectGLJDiffPrice(data);
        activeSheet.setValue(rowCounter,basePriceColumn,data.base_price);
        activeSheet.setValue(rowCounter,adjustPriceColumn,data.adjust_price);
        if(rowStyle==null&&data.base_price == data.unit_price.market_price){//如果定额价等于市场价时，改底色。 优先度低于有组成物时的底色
            rowStyle = this.getRowStyle("#C4CAFB");
        }
        activeSheet.setStyle(rowCounter, -1, rowStyle);

        rowCounter++;
    }
};

ProjectGLJSpread.prototype.getRowStyle = function (bgColour) {
    let style = new GC.Spread.Sheets.Style();
    style.backColor = bgColour;
    style.borderLeft = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
    style.borderTop = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
    style.borderRight = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
    style.borderBottom = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
    return style;
};

/**
 * 计算当前行对应组成物的市场以及基价单价价格
 *
 * @param {Number} row
 * @return {Object}
 */
ProjectGLJSpread.prototype.compositionCalculate = function(updateRecord) {
    let gljData = projectObj.project.projectGLJ.datas;
    let m_index = gljOprObj.getIndex(updateRecord,gljKeyArray);
    let parent_connect_keys = gljData.mixRatioConnectData[m_index];
    if(!parent_connect_keys||parent_connect_keys.length<=0){// 不属于组成物则忽略
        return null;
    }
    let q_decimal = getDecimal("glj.quantity");
    let p_decimal = getDecimal("glj.unitPrice");
    let parentMarketPrice = {};
    for(let p  of parent_connect_keys) {
        let mix_ratios = gljData.mixRatioMap[p];
        let sum = 0;
        for (let m of mix_ratios) {
            let unitPrice = this.sheetObj.getUnitPrice(m);
            if (unitPrice) {
                let com = scMathUtil.roundForObj(m.consumption, q_decimal);
                let marketPrice = scMathUtil.roundForObj(unitPrice.market_price, p_decimal);
                sum = scMathUtil.roundForObj(marketPrice * com + sum, p_decimal);
            }
        }
        parentMarketPrice[p]=sum;
    }
    return parentMarketPrice;
};

/**
 * 组成物父类数据更新
 *
 * @param {Object} parentMarketPrice
 * @return {void}
 */
ProjectGLJSpread.prototype.compositionParentUpdate = function(parentMarketPrice) {
    let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
    let activeSheet = this.sheetObj.getSheet();
    // 定位到父节点，然后更新
    for (let code in parentMarketPrice) {
        let changeRow = this.sheetObj.searchKeyword(code);
        activeSheet.setValue(changeRow, marketPriceColumn, parentMarketPrice[code]);
    }
};

/**
 * 价格计算
 *
 * @param {Object} info
 * @return {void}
 */
ProjectGLJSpread.prototype.priceCalculate = function(info) {
    let row = info.row;
    let typeColumn = this.sheetObj.getFieldColumn('unit_price.type');
    let basePriceColumn = this.sheetObj.getFieldColumn('base_price');
    let adjustPriceColumn = projectGLJSheet.getFieldColumn('adjust_price');
    let activeSheet = this.sheetObj.getSheet();

    // 获取类型
    let type = activeSheet.getValue(row, typeColumn);
  /*  let data = jsonData[row];
    if(gljOprObj.calcPriceDiff(data)==true){//是否记算价差
        data.base_price = data.unit_price.base_price;
        data.adjust_price = projectObj.project.projectGLJ.getAdjustPrice(data);
    }else {
        data.base_price = data.unit_price.market_price;
        data.adjust_price = data.unit_price.market_price;
    }
    activeSheet.setValue(info.row,basePriceColumn,data.base_price);
    activeSheet.setValue(info.row,adjustPriceColumn,data.adjust_price);*/


  /*  // 基价单价计算
    switch (type) {
        // 主材、设备自动赋值基价单价=市场单价
        case GLJTypeConst.MAIN_MATERIAL:
        case GLJTypeConst.EQUIPMENT:
            activeSheet.setValue(info.row, basePriceColumn, info.newValue);
            break;
    }*/

 /*   // 调整基价计算
    switch (type) {
        // 材料、主材、设备 调整基价=基价单价
        case GLJTypeConst.MAIN_MATERIAL:
        case GLJTypeConst.EQUIPMENT:
            let basePrice = activeSheet.getValue(info.row, basePriceColumn);
            activeSheet.setValue(info.row, adjustPriceColumn, basePrice);
            break;

    }*/

    // 市场单价计算
    switch (type) {
        // 人工、材料(普通材料)触发 需计算混凝土、砂浆、配合比、机械的市场单价
        case GLJTypeConst.LABOUR:
        case GLJTypeConst.GENERAL_MATERIAL:
            // 计算
            this.compositionParentUpdate(info.parentMarketPrice);
            break;
    }
};

/**
 * 更改供货方式
 *
 * @param {Object} info
 * @return {void}
 */
ProjectGLJSpread.prototype.changeSupplyType = function(info) {
    // let supply = info.newValue;
    // let supplyNumber = this.supplyType.indexOf(supply) > -1 ? this.supplyType.indexOf(supply) : 0;
    let supplyNumber = info.newValue;
    let supplyQuantityColumn = this.sheetObj.getFieldColumn('supply_quantity');
    let activeSheet = this.sheetObj.getSheet();

    // 部分甲供时可更改甲供数量数据,其余则只读
    let locked = supplyNumber == 1 ? false : true;
    activeSheet.getCell(info.row, supplyQuantityColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(locked);

    let supplyQuantity = this.getSupplyQuantity(supplyNumber, activeSheet, info);
    activeSheet.setValue(info.row, supplyQuantityColumn, supplyQuantity);
};

/**
 * 根据供货方式获取甲供数量
 *
 * @param {Number} supplyType
 * @param {Object} activeSheet
 * @param {Object} info
 * @return {Number}
 */
ProjectGLJSpread.prototype.getSupplyQuantity = function(supplyType, activeSheet, info) {
    let quantityColumn = this.sheetObj.getFieldColumn('quantity');
    // 获取总消耗量
    let quantity = activeSheet.getValue(info.row, quantityColumn);
    // 自行采购和甲定乙供则把甲供数量设置为0，其余情况则设置为当前总消耗量
    let supplyQuantity = supplyType == 0 || supplyType == 3 ? 0 : quantity;
    supplyQuantity = parseFloat(supplyQuantity);

    return supplyQuantity;
};