/**
 * 项目工料机列表数据模型
 *
 * @author CaiAoLin
 * @date 2017/6/22
 * @version
 */
import BaseModel from "../../common/base/base_model";
import {default as GLJSchemas, collectionName as gljCollectionName} from "./schemas/glj";
import CounterModel from "./counter_model";
import UnitPriceModel from "./unit_price_model";
import UnitPriceFileModel from "./unit_price_file_model";

class GLJListModel extends BaseModel {

    /**
     * 材料类型id
     *
     * @var {Array}
     */
    materialIdList = [5, 6, 7];

    /**
     * 构造函数
     *
     * @return {void}
     */
    constructor() {
        let parent = super();
        parent.model = GLJSchemas;
        parent.init();
    }

    /**
     * 设置场景
     *
     * @param {string} scene
     * @return {void}
     */
    setScene(scene = '') {
        switch (scene) {
            // 新增数据的验证规则
            case 'add':
                this.model.schema.path('glj_repository_id').required(true);
                this.model.schema.path('project_id').required(true);
                this.model.schema.path('code').required(true);
                this.model.schema.path('name').required(true);
                break;
        }
    }

    /**
     * 根据标段对应工料机数据
     *
     * @param {Number} projectId
     * @return {Promise}
     */
    async getListByProjectId(projectId) {
        let gljData = null;
        try {
            // 首先获取对应标段下所有的项目工料机数据
            let condition = {project_id: projectId};
            let fields = {_id: 0};
            gljData = await this.db.find(condition, fields);

            // 没有数据则直接返回空
            if (gljData.length <= 0) {
                throw '无数据';
            }

            // 获取标段对应的单价文件id
            let unitPriceFileModel = new UnitPriceFileModel();
            let unitPriceFile = await unitPriceFileModel.getDataByProject(projectId);
            if (!unitPriceFile) {
                throw '没有对应的单价文件';
            }
            let unitPriceFileId = unitPriceFile.id;

            // 获取标段设置的单价文件数据
            let unitPriceModel = new UnitPriceModel();
            let unitPriceList = await unitPriceModel.getDataByFileId(unitPriceFileId);

            // 组合数据
            this.combineUnitPrice(gljData, unitPriceList);

            // 排序
            gljData.sort(function (a, b) {
                return a.unit_price.type - b.unit_price.type;
            });
        } catch (error) {
            console.log("glj_list_model:" + error);
            gljData = [];
        }

        return gljData;
    }

    /**
     * 组合工料机数据和单价文件数据
     *
     * @param {object} gljList
     * @param {object} unitPriceList
     * @return {void}
     */
    combineUnitPrice(gljList, unitPriceList) {
        // @todo 以后从js获取？
        let labour = 2;
        let machine = 64;

        // 循环组合数据
        for(let glj of gljList) {
            if (glj.code === undefined) {
                continue;
            }
            glj.unit_price = unitPriceList[glj.code + glj.name] !== undefined ? unitPriceList[glj.code + glj.name] : null;
            // 计算调整基价
            switch (glj.type + '') {
                // 人工: 调整基价=基价单价*调整系数
                case labour:
                    glj.adjust_price = glj.adjustment * glj.unit_price.base_price;
                    break;
                // 机械类型的算法
                case machine:
                    console.log('机械');
                    break;
                // 材料、主材、设备
                default:
                    glj.adjust_price = glj.unit_price.base_price;
            }

        }
    }

    /**
     * 新增项目工料机数据(包括新增单价文件) 定额工料机新增时调用
     *
     * @param {object} data
     * @return {Promise} 返回插入成功的数据id
     */
    async addList(data) {
        let result = null;
        try {
            if (Object.keys(data).length <= 0) {
                throw '新增数据为空';
            }
            // 首先查找是否有同编码同名称的工料机数据
            let projectGljData = await this.findDataByCondition({code: data.code, project_id: data.project_id});
            // 如果找不到数据则新增
            if (!projectGljData) {
                // 新增单条记录 （两个操作本来应该是事务操作，然而mongodb事务支持比较弱，就当作是都可以顺利执行）
                let gljInsertData = await this.add(data);
                if (!gljInsertData) {
                    throw '新增项目工料机失败!';
                }
                projectGljData = gljInsertData;
            }

            // 获取标段对应的单价文件id
            let unitPriceFileModel = new UnitPriceFileModel();
            let unitPriceFile = await unitPriceFileModel.getDataByProject(data.project_id);
            if (!unitPriceFile) {
                throw '没有对应的单价文件';
            }
            let unitPriceFileId = unitPriceFile.id;

            // 新增单价文件
            let unitPriceModel = new UnitPriceModel();
            let [unitPriceInsertData, isAdd] = await unitPriceModel.addUnitPrice(data, unitPriceFileId);

            if (!unitPriceInsertData) {
                throw '新增单价失败!';
            }

            projectGljData.unit_price = unitPriceInsertData;
            result = projectGljData;
        } catch (error) {
            console.log(error);
            result = null;
        }

        return result;
    }

    /**
     * 新增单条工料机数据
     *
     * @param {object} data
     * @return {Promise}
     */
    async add(data) {
        if (Object.keys(data).length <= 0) {
            throw '新增数据为空';
        }

        let counterModel = new CounterModel();
        data.id = await counterModel.getId(gljCollectionName);

        this.setScene('add');
        let result = await this.db.create(data);
        return result;
    }

    /**
     * 根据工料机id修改市场单价
     *
     * @param {Object} updateData
     * @return {Promise}
     */
    async modifyMarketPrice(updateData) {
        let result = {};
        try {
            if (updateData.code === undefined || updateData.market_price === undefined ||
                updateData.name === undefined || updateData.project_id === undefined) {
                throw '参数有误!';
            }

            // 先查是否有对应code的数据
            let gljListData = await this.findDataByCondition({code: updateData.code,
                project_id: updateData.project_id}, {_id: 0}, false);
            if (!gljListData) {
                throw '不存在对应code数据';
            }

            // 获取标段对应的单价文件id
            let unitPriceFileModel = new UnitPriceFileModel();
            let unitPriceFile = await unitPriceFileModel.getDataByProject(updateData.project_id);
            if (!unitPriceFile) {
                throw '没有对应的单价文件';
            }
            let unitPriceFileId = unitPriceFile.id;
            let unitPriceModel = new UnitPriceModel();

            let gljCount = gljListData.length;
            let [unitPriceData, isAdd] = await unitPriceModel.addUnitPrice(updateData, unitPriceFileId, gljCount);

            // 判断是否已存在对应数据
            let includeField = [
                {field: 'name', value: unitPriceData.name}
            ];
            let gljIndex = this.isIncluded(gljListData, includeField);
            let gljData = isAdd ? {} : gljListData[gljIndex];

            // 如果单价数据新增则工料机也需要新增
            if (isAdd) {
                // 如果没有对应的记录则新增一条工料机数据，并更改name
                let regular = /\(\d\)/;
                let changeString = '(' + gljCount + ')';
                updateData.name = regular.test(updateData.name) ? updateData.name.replace(regular, changeString) :
                    updateData.name + changeString;

                // 获取第一条数据作为数据源
                let originalData = gljListData[0];

                // 更改名称
                originalData.name = updateData.name;
                originalData = JSON.stringify(originalData);
                gljData = await this.add(JSON.parse(originalData));
                if (!gljData) {
                    throw '新增工料机数据失败!';
                }
            }

            gljData.unit_price = unitPriceData;

            result = gljData;
        } catch (error) {
            console.log(error);
            result = {};
        }

        return result;
    }

    /**
     * 判断数据中是否包含某个数据
     *
     * @param {Array} data
     * @param {Array} includeField
     * @return {Number}
     */
    isIncluded(data, includeField) {
        let index = -1;
        if (data.length <= 0) {
            return index;
        }
        for(let tmp in data) {
            let counter = 0;
            for (let includeTmp of includeField) {
                if (data[tmp][includeTmp.field] === includeTmp.value) {
                    counter++;
                }
            }
            if (counter === includeField.length) {
                index = tmp;
                break;
            }
        }

        return index;
    }
}

export default GLJListModel;
