/**
 * Created by zhang on 2018/6/7.
 */


let gljUtil = {
    calcProjectGLJQuantity:function (projectGLJDatas,rationGLJDatas,rationDatas,billsDatas,q_decimal,_,scMathUtil,isTender) {
        let project_gljs = projectGLJDatas.gljList;
        let mixRatioMap = projectGLJDatas.mixRatioMap;
        let rations = rationDatas;
        let rationMap = _.indexBy(rations,'ID');
        let quantityMap={};
        let rationGljGroup = _.groupBy(rationGLJDatas,'projectGLJID');
        let IDarray =  this.getSubdivisionAndTechBillsLeavesID(billsDatas);//分别取分部分项和技术措施项目的所有叶子清单ID
        let billIDs = IDarray[0],tech_billIDS = IDarray[1];
        let sField = isTender==true?"tenderSubdivisionQuantity":"subdivisionQuantity";
        let tField = isTender==true?"tenderTechQuantity":"techQuantity";
        let qField = isTender==true?"tenderQuantity":"quantity";

        for(let pglj of project_gljs ){
            let pg_index = this.getIndex(pglj,this.gljKeyArray);
            pglj[sField] = 0;
            pglj[tField] = 0;
            pglj[qField] = 0;
            let gljGroup = rationGljGroup[pglj.id]?rationGljGroup[pglj.id]:[];//定额工料机没有，有可能是定额类型的工料机
            let result = this.getQuantityPerGLJ(gljGroup,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil,isTender);
            pglj[sField] = result.subdivisionQuantity;
            pglj[tField] = result.techQuantity;
            pglj[qField] = result.quantity;
            quantityMap[pg_index] = pglj;
        }
        //计算做为组成物的消耗量
        for(let pkey in mixRatioMap){
            let mixRatioList = mixRatioMap[pkey];
            for(let m of mixRatioList){
                let m_index = this.getIndex(m,this.gljKeyArray);
                let m_glj = quantityMap[m_index];
                let p_glj = quantityMap[pkey];
                if(m_glj&&p_glj){
                    let quantity = scMathUtil.roundForObj(parseFloat(p_glj[qField])*parseFloat(m.consumption),q_decimal);
                    let techQuantity = scMathUtil.roundForObj(parseFloat(p_glj[tField])*parseFloat(m.consumption),q_decimal);
                    let subdivisionQuantity = scMathUtil.roundForObj(parseFloat(p_glj[sField])*parseFloat(m.consumption),q_decimal);
                    m_glj[qField] =  scMathUtil.roundForObj(parseFloat(m_glj[qField])+quantity,q_decimal);
                    m_glj[tField] =  scMathUtil.roundForObj(parseFloat(m_glj[tField])+techQuantity,q_decimal);
                    m_glj[sField] =  scMathUtil.roundForObj(parseFloat(m_glj[sField])+subdivisionQuantity,q_decimal);
                }
            }
        }
    },
    getQuantityPerGLJ : function (ration_glj_list,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil,isTender) {
        let result={};
        let quantity_sum=0;//工料机汇总消耗量
        let sum = 0;//分部分项总消耗量
        let tech_sum = 0;//技术措施总消耗量
        for(let rg of ration_glj_list){
            let tem_ration = rationMap[rg.rationID];
            let r_quantity = tem_ration?scMathUtil.roundForObj(tem_ration.quantity,q_decimal):0;
            let glj_quantity = scMathUtil.roundForObj(rg.quantity, q_decimal);
            if(!r_quantity){
                continue;
            }
            if(isTender == true){
                glj_quantity = this.getRationGLJTenderQuantity(rg,tem_ration,q_decimal,scMathUtil);
                r_quantity = this.getRationTenderQuantity(tem_ration,q_decimal,scMathUtil);
            }
            let total = scMathUtil.roundForObj(glj_quantity*r_quantity, q_decimal);
            quantity_sum = scMathUtil.roundForObj(quantity_sum+total,q_decimal);
            if(_.includes(billIDs,rg.billsItemID)){//计算分部分项
                sum = scMathUtil.roundForObj(sum+total,q_decimal);
            }
            if(_.includes(tech_billIDS,rg.billsItemID)){//计算技术措施项目消耗量
                tech_sum = scMathUtil.roundForObj(tech_sum+total,q_decimal);
            }
        }
        for(let ra of rations){//计算定额类型工料机的消耗量
            if(ra.type == this.rationType.gljRation&&ra.projectGLJID===pglj.id){
                let r_quantity = scMathUtil.roundForObj(ra.quantity,q_decimal);
                r_quantity = r_quantity?r_quantity:0;
                if(isTender == true){
                    r_quantity = this.getRationTenderQuantity(ra,q_decimal,scMathUtil);
                }
                quantity_sum = scMathUtil.roundForObj(quantity_sum+r_quantity,q_decimal);
                if(_.includes(billIDs,ra.billsItemID)){//计算分部分项
                    sum = scMathUtil.roundForObj(sum+r_quantity,q_decimal);
                }
                if(_.includes(tech_billIDS,ra.billsItemID)){//计算技术措施项目消耗量
                    tech_sum = scMathUtil.roundForObj(tech_sum+r_quantity,q_decimal);
                }
            }

        }
        result.subdivisionQuantity = sum;
        result.techQuantity = tech_sum;
        result.quantity = quantity_sum;
        return result;
    },
    getRationGLJTenderQuantity:function (ration_glj,ration,q_decimal,scMathUtil) {
        let coeMap = {
          1:'labour',  //人工
          2:'material',//材料
          3:'machine',//机械
          4:'main', //主材
          5:'equipment'//设备
        };
        let typeString = ration_glj.type +"";
        let coeField = "";
        for(let key in coeMap){
            if(typeString.indexOf(key)!= -1){
              coeField = coeMap[key];
            }
        }
        let coe = ration.quantityCoe&&this.isNotEmpty(ration.quantityCoe[coeField])?ration.quantityCoe[coeField]:1;
        coe = parseFloat(coe);
        let glj_quantity = scMathUtil.roundForObj(ration_glj.quantity, q_decimal);
        return scMathUtil.roundForObj(glj_quantity * coe,q_decimal);
    },
    getRationTenderQuantity:function (ration,q_decimal,scMathUtil) {
        let rationQuantityCoe = this.isNotEmpty(ration.rationQuantityCoe)?ration.rationQuantityCoe:1;
        rationQuantityCoe = parseFloat(rationQuantityCoe);
        let r_quantity = ration?scMathUtil.roundForObj(ration.quantity,q_decimal):0;
        return scMathUtil.roundForObj(r_quantity * rationQuantityCoe,q_decimal);
    },
    isNotEmpty:function (str) {
        return this.isDef(str) && str!="";
    },
    getSubdivisionAndTechBillsLeavesID:function (billsDatas) {//分别取分部分项和技术措施项目的所有叶子清单ID
         if(typeof (projectObj) !== 'undefined'){//存在，说明在前端调用
             return [projectObj.project.Bills.getSubdivisionProjectLeavesID(),projectObj.project.Bills.getTechLeavesID()];
         }
        let parentMap ={};
        let subdivisionBillID  = null,techBillID = null,sIDs = [],tIDS = [];
        for(let b of billsDatas){
            if(parentMap[b.ParentID]){
                parentMap[b.ParentID].push(b);
            }else {
                parentMap[b.ParentID]= [b];
            }
            let flag = this.getFlag(b);
            if(this.isDef(flag)&&flag.flag == this.fixedFlag.SUB_ENGINERRING){
                subdivisionBillID = b.ID;
            }
            if(this.isDef(flag)&&flag.flag == this.fixedFlag.CONSTRUCTION_TECH){
                techBillID = b.ID;
            }
        }

        getLeaveIDs(subdivisionBillID,parentMap,sIDs);
        getLeaveIDs(techBillID,parentMap,tIDS);
        return [sIDs,tIDS];

        function getLeaveIDs(ID,parentM,leaveIDs) {
            if(parentM[ID] && parentM[ID].length > 0){
                let children  =  parentM[ID];
                for(let c of children){
                    if(parentM[c.ID]){
                        getLeaveIDs(c.ID,parentM,leaveIDs);
                    }else {
                        leaveIDs.push(c.ID);
                    }
                }
            }
        }
    },
    getFlag:function (b) {
        return _.find(b.flags,{"fieldName":"fixed"});
    },
    getGLJPrice:function (glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil) {
        let result = {};
        result.marketPrice = this.getMarketPrice(glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil);
        if(this.calcPriceDiff(glj,calcOptions)==true){//计取价差
            result.basePrice = this.getBasePrice(glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil);
            result.adjustPrice = this.getAdjustPrice(glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil);
        }else {//不计价差
            result.basePrice = result.marketPrice;
            result.adjustPrice = result.marketPrice;
        }
        return result;
    },
    getMarketPrice:function (glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil,tenderCoe) {
        let price_decimal = decimalObj.glj.unitPrice;
        let price_hasM_decimal = decimalObj.glj.unitPriceHasMix?decimalObj.glj.unitPriceHasMix:decimalObj.glj.unitPrice;
        let quantity_decimal = decimalObj.glj.quantity;
        let process_decimal = decimalObj.process;
        let priceCoe = this.isDef(tenderCoe)?tenderCoe:1;
        if (this.notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班等有组成物的材料，价格需根据组成物计算得出。
            let p =0;
            for(let ratio of glj.ratio_data){
                let tem =  _.find(projectGLJDatas.gljList,{
                    'code': ratio.code,
                    'name': ratio.name,
                    'specs':ratio.specs,
                    'type': ratio.type,
                    'unit': ratio.unit
                });
                if(tem){
                    let priceData=this.getGLJPrice(tem,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,true,_,scMathUtil);
                    let temP = scMathUtil.roundForObj(priceData.marketPrice* priceCoe * scMathUtil.roundForObj(ratio.consumption,quantity_decimal),process_decimal);
                    p = scMathUtil.roundForObj(temP + p,process_decimal);
                }
            }
            return scMathUtil.roundForObj(p,price_hasM_decimal);
        }else {
            let tem_decimal =price_decimal; //isRadio==true?process_decimal:price_decimal;
            let tem_price = scMathUtil.roundForObj(glj.unit_price.market_price,price_decimal);
            return scMathUtil.roundForObj(tem_price*priceCoe,tem_decimal);
        }
    },
    getBasePrice:function (glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil) {
        let price_decimal = decimalObj.glj.unitPrice;
        let price_hasM_decimal = decimalObj.glj.unitPriceHasMix?decimalObj.glj.unitPriceHasMix:decimalObj.glj.unitPrice;
        let quantity_decimal = decimalObj.glj.quantity;
        let process_decimal = decimalObj.process;

        if (this.notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班等有组成物的材料，价格需根据组成物计算得出。
            //2018-09-07 需求修改，定额价不按组成物的量和价实时计算出来，直接取单价文件中的定额价
       /*     let p =0;
            for(let ratio of glj.ratio_data){
                let tem =  _.find( projectGLJDatas.gljList,{
                    'code': ratio.code,
                    'name': ratio.name,
                    'specs':ratio.specs,
                    'type': ratio.type,
                    'unit': ratio.unit
                });
                if(tem){
                    let priceData=this.getGLJPrice(tem,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,true,_,scMathUtil);
                    let temP = scMathUtil.roundForObj(priceData.basePrice*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),process_decimal);
                    p = scMathUtil.roundForObj(temP + p,process_decimal);
                }
            }
            return scMathUtil.roundForObj(p,price_hasM_decimal);*/

            return scMathUtil.roundForObj(glj.unit_price.base_price,price_hasM_decimal);
        }else {
            let tem_decimal =price_decimal; //isRadio==true?process_decimal:price_decimal;
            return scMathUtil.roundForObj(glj.unit_price.base_price,tem_decimal);
        }
    },
    getAdjustPrice:function (glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil) {
        let decimal = decimalObj.glj.unitPrice;
        let price_hasM_decimal = decimalObj.glj.unitPriceHasMix?decimalObj.glj.unitPriceHasMix:decimalObj.glj.unitPrice;
        let quantity_decimal =  decimalObj.glj.quantity;
        let process_decimal = decimalObj.process;
        let  tem_decimal = isRadio==true?process_decimal:decimal;
        if (glj.unit_price.type == this.gljType.LABOUR || glj.unit_price.type == this.gljType.MACHINE_LABOUR) {//人工、机上人工，调整价根据定额价*调整系数计算得出。
            let labour = _.find(labourCoeDatas.coes,{'ID':glj.adjCoe});
            let coe = labour && labour.coe ? labour.coe : 1;
            return scMathUtil.roundTo(parseFloat(coe * scMathUtil.roundForObj(glj.unit_price.base_price,decimal)), -decimal);
        } else if (this.notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班，调整价根据组成物计算得出。
            let p =0;
            for(let ratio of glj.ratio_data){
                let tem =  _.find( projectGLJDatas.gljList,{
                    'code': ratio.code,
                    'name': ratio.name,
                    'specs':ratio.specs,
                    'type': ratio.type,
                    'unit': ratio.unit
                })
                if(tem){
                    let priceData=this.getGLJPrice(tem,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,true,_,scMathUtil);
                    let temP = scMathUtil.roundForObj(priceData.adjustPrice*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),process_decimal);
                    p = scMathUtil.roundForObj(temP + p,process_decimal);
                }
            }
            return scMathUtil.roundForObj(p,price_hasM_decimal);
        } else {//对于其他普通材料等，无调整系数，调整价=定额价。
            return  scMathUtil.roundForObj(glj.unit_price.base_price,decimal)
        }
    },
    calcPriceDiff:function (glj,calcOptions) {
        if(glj.is_evaluate==1){//先按是否暂估判断
            return calcOptions.calc_est;
        }
        if(glj.type==gljType.MAIN_MATERIAL||glj.type==gljType.EQUIPMENT){//再判断是否是主材和设备
            return calcOptions.calc_main;
        }
        if(glj.unit_price.is_add==1){//再判断是否新增
            return calcOptions.calc_add;
        }
        return true;
    },
    isFlag : function (v) {
        return this.isDef(v.flagsIndex) && this.isDef(v.flagsIndex.fixed) && this.isDef(v.flagsIndex.fixed.flag);
    },
    isDef:function (v) {
        return v !== undefined && v !== null;
    },
    getIndex(obj, pops){
        let t_index = '';
        let k_arr = [];
        for (let p of pops) {
            let tmpK = (obj[p] == undefined || obj[p] == null || obj[p] == '') ? 'null' : obj[p];
            k_arr.push(tmpK);
        }
        t_index = k_arr.join("|-|");
        return t_index;
    },
    getGljTypeSeq:function () {
        let gljType = this.gljType;
        return   [gljType.LABOUR,gljType.MAIN_MATERIAL,gljType.CONCRETE,gljType.MORTAR,gljType.MIX_RATIO,gljType.COMMERCIAL_CONCRETE,
                gljType.COMMERCIAL_MORTAR,gljType.GENERAL_MATERIAL,gljType.OTHER_MATERIAL,gljType.GENERAL_MACHINE,gljType.INSTRUMENT,gljType.OTHER_MACHINE_USED,
                gljType.MACHINE_COMPOSITION,gljType.MACHINE_LABOUR,gljType.FUEL_POWER_FEE,gljType.DEPRECIATION_FEE,gljType.INSPECTION_FEE,gljType.MAINTENANCE,
                gljType.DISMANTLING_FREIGHT_FEE,gljType.VERIFICATION_FEE,gljType.OTHER_FEE,gljType.EQUIPMENT,gljType.MANAGEMENT_FEE,gljType.PROFIT,gljType.GENERAL_RISK_FEE]
    },
    sortRationGLJ:function (list) {
        list = _.sortByAll(list, [function (item) {
            return _.indexOf(gljTypeSeq,item.type)
        }, "code"])
        return list;
    },
    fixedFlag : {
        // 分部分项工程
        SUB_ENGINERRING: 1,
        // 措施项目
        MEASURE: 2,
        // 施工技术措施项目
        CONSTRUCTION_TECH: 3
    },
    gljType : {
        LABOUR: 1,                                  // 人工
        // ==============材料类型 ↓=================
        GENERAL_MATERIAL: 201,                      // 普通材料
        CONCRETE: 202,                              // 混凝土
        MORTAR: 203,                                // 砂浆
        MIX_RATIO: 204,                             // 配合比
        COMMERCIAL_CONCRETE: 205,                   // 商品混凝土
        COMMERCIAL_MORTAR: 206,                     // 商品砂浆
        OTHER_MATERIAL: 207,                        // 其它材料
        // ==============材料类型 ↑=================
        // ==============机械类型 ↓=================
        GENERAL_MACHINE: 301,                       // 机械台班
        MACHINE_COMPOSITION: 302,                   // 机械组成物
        MACHINE_LABOUR: 303,                        // 机上人工
        INSTRUMENT: 304,                            // 仪器仪表
        FUEL_POWER_FEE:305,                         // 燃料动力费
        DEPRECIATION_FEE:306,                       // 折旧费
        INSPECTION_FEE:307,                         // 检修费
        MAINTENANCE:308,                            // 维护费
        DISMANTLING_FREIGHT_FEE:309,                // 安拆费及场外运费
        VERIFICATION_FEE:310,                       // 校验费
        OTHER_FEE:311,                              // 其他费用
        OTHER_MACHINE_USED:312,                     // 其他施工机具使用费
        // ==============机械类型 ↑=================
        MAIN_MATERIAL: 4,                           // 主材
        EQUIPMENT: 5,                               // 设备
        MANAGEMENT_FEE: 6,                          // 企业管理费
        PROFIT: 7,                                  // 利润
        GENERAL_RISK_FEE: 8                         // 一般风险费
    },
    extraType:[6,7,8],//一些其它的工料机类型
    notEditType : [202,203,204,301,304,4],
    gljKeyArray : ['code','name','specs','unit','type'],
    rationType : {
        ration: 1,
        volumePrice: 2,
        gljRation: 3,
        install:4
    },
    hasCompMaterial:[202, 203, 204],//有组成物的材料
    hasCompMachine:[301],//有组成物的机械
    machineComposition:[302,303]//可以做为机械组成物的类型
}