/**
 * 项目工料机相关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;
}

/**
 * 初始化
 *
 * @return {object}
 */
ProjectGLJSpread.prototype.init = function () {

    let header = [
        {name: '编码', field: 'code', visible: true},
        {name: '名称', field: 'name', visible: true},
        {name: '规格型号', field: 'specs', visible: true},
        {name: '单位', field: 'unit', visible: true},
        {name: 'ID', field: 'id', visible: false},
        {name: '类型', field: 'unit_price.type', visible: false},
        {name: '总消耗量', field: 'quantity', visible: true},
        {name: '基价单价', field: "unit_price.base_price", visible: true},
        {name: '调整基价', field: 'adjust_price', visible: true},
        {name: '市场单价', field: "unit_price.market_price", visible: true, validator: 'number'},
        {
            name: '是否暂估',
            field: 'is_evaluate',
            visible: true,
            cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),
            validator: 'boolean'
        },
        {name: '供货方式', field: 'supply', visible: true},
        {name: '甲供数量', field: 'supply_quantity', visible: true},
        {name: '交货方式', field: 'delivery', visible: true},
        {name: '送达地点', field: 'delivery_address', visible: true},
        {
            name: '不调价',
            field: 'is_adjust_price',
            visible: true,
            cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),
            validator: 'boolean'
        },
        {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},
    ];
    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('unit_price.base_price');
    let adjustPriceColumn = this.sheetObj.getFieldColumn('adjust_price');
    let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');

    // 居中样式
    let centerStyleSetting = {hAlign: 1};
    this.sheetObj.setStyle(-1, isEvaluateColumn, centerStyleSetting);
    this.sheetObj.setStyle(-1, isAdjustPriceColumn, centerStyleSetting);
    this.sheetObj.setStyle(-1, unitColumn, 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.setColumnEditable(marketPriceColumn);
    this.sheetObj.setColumnEditable(isEvaluateColumn);
    this.sheetObj.setColumnEditable(isAdjustPriceColumn);
    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);

        // 如果类型为混凝土、砂浆、配合比、机械，则提示
        if (field === 'unit_price.market_price' && canNotChangeTypeId.indexOf(type) >= 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 parentMarketPrice = projectGLJSpread.compositionCalculate(row);
    if (parentMarketPrice !== null && Object.keys(parentMarketPrice).length > 0) {
        for (let activeCode in parentMarketPrice) {
            let tmpObject = {
                market_price: parentMarketPrice[activeCode],
            };
            extend[activeCode] = tmpObject;
        }
    }

    extend = Object.keys(extend).length > 0 ?  JSON.stringify(extend) : '';
    $.ajax({
        url: '/glj/update',
        type: 'post',
        data: {id: id, field: field, value: value, extend: extend},
        dataType: 'json',
        error: function() {
            alert('数据传输有误!');
            isChanging = false;
        },
        beforeSend: function() {
            isChanging = true;
        },
        success: function(response) {
            isChanging = false;
            // 修改失败则恢复原值
            if (response.err !== 0) {
                activeSheet.setValue(row, column, info.oldValue);
                alert('更改数据失败!');
            } else {
                // 成功则触发相应事件
                if (parentMarketPrice !== null) {
                    info.parentMarketPrice = parentMarketPrice;
                }
                callback(field, info);
            }
        }
    });
};

/**
 * 设置特殊单元格数据
 *
 * @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 connectCodeColumn = this.sheetObj.getFieldColumn('connect_code');
    let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
    let activeSheet = this.sheetObj.getSheet();

    for (let data of sourceData) {
        // 只有材料才显示是否暂估
        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.getRange(rowCounter, isEvaluateColumn, 1, 1).locked(true);
            activeSheet.setValue(rowCounter, isEvaluateColumn, '');
        }

        // 如果类型为混凝土、砂浆、配合比、机械，则市场单价不能修改
        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;
            // 锁定该单元格
            activeSheet.getRange(rowCounter, marketPriceColumn, 1, 1).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_code);
                consumption.push(tmp.consumption);
            }
            let connectCodeString = connectCode.join(',');
            let consumptionString = consumption.join(',');
            activeSheet.setValue(rowCounter, connectCodeColumn, connectCodeString);
            activeSheet.setValue(rowCounter, consumptionColumn, consumptionString);
        }
        rowCounter++;
    }
};

/**
 * 计算当前行对应组成物的市场以及基价单价价格
 *
 * @param {Number} row
 * @return {Object}
 */
ProjectGLJSpread.prototype.compositionCalculate = function(row) {
    let activeSheet = this.sheetObj.getSheet();
    // 获取相关列号
    let connectCodeColumn = this.sheetObj.getFieldColumn('connect_code');
    let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
    let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');

    let activeConnectCode = activeSheet.getValue(row, connectCodeColumn);
    // 不属于组成物则忽略
    if (activeConnectCode === '' || activeConnectCode === null) {
        return null;
    }
    activeConnectCode = activeConnectCode.split(',');
    // 计算同级组成物的价格
    // 遍历所有记录
    let maxRow = activeSheet.getRowCount();

    let parentMarketPrice = {};
    for (let i = 0; i < maxRow; i++) {
        let connectCode = activeSheet.getValue(i, connectCodeColumn);
        if (connectCode === null) {
            continue;
        }
        connectCode = connectCode.split(',');
        // 消耗量
        let consumption = activeSheet.getValue(i, consumptionColumn);
        consumption = consumption.split(',');

        // 获取市场价
        let marketPrice = activeSheet.getValue(i, marketPriceColumn);

        for (let active of activeConnectCode) {
            let index = connectCode.indexOf(active);
            if (index < 0) {
                continue;
            }
            let rowConsumption = consumption[index] === undefined ? 0 : consumption[index];
            // 计算价格
            let rowMarketPrice = (marketPrice * rowConsumption).toDecimal(2);
            parentMarketPrice[active] = parentMarketPrice[active] === undefined ?
                rowMarketPrice : (parentMarketPrice[active] + rowMarketPrice).toDecimal(2);

        }

    }

    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('unit_price.base_price');
    let adjustPriceColumn = projectGLJSheet.getFieldColumn('adjust_price');
    let activeSheet = this.sheetObj.getSheet();

    // 获取类型
    let type = activeSheet.getValue(row, typeColumn);

    // 基价单价计算
    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;
    }
};