/**
 * Created by chen on 2017/7/12.
 */


let mongoose = require('mongoose');
let _=require("lodash");
let ration_glj = mongoose.model('ration_glj');
let ration = mongoose.model('ration');
let ration_coe = mongoose.model('ration_coe');
let std_ration_lib_ration_items = mongoose.model('std_ration_lib_ration_items');
let glj_type_util = require('../../../public/cache/std_glj_type_util');


module.exports={
    calculateQuantity:calculateQuantity,
    getGLJTypeByID:getGLJTypeByID
}
//辅助定额调整、替换工料机、标准附注条件调整、添加工料机、自定义消耗量(包括删除工料机)、自定义乘系数、市场单价调整
let stateSeq ={
    ass:1,
    replase:2,
    coe:3,
    add:4,
    cusQuantity:5,
    cusCoe:6,
    adjMak:7
}


async function calculateQuantity(query,isMarkPriceAjust){
    try {
         let  result ={
             glj_result:[],
             rationID:query.rationID
         };
         let impactRation = await ration.findOne({projectID:query.projectID,ID:query.rationID,deleteInfo:null});
         let gljList = await ration_glj.find(query)//{projectID:query.projectID,rationID:query.rationID}
         let coeList = await ration_coe.find({projectID:query.projectID,rationID:query.rationID}).sort('seq').exec();
         let assList=[];
         let assRation = null;
         let adjustState=[];
         if(impactRation._doc.hasOwnProperty("rationAssList")&&impactRation.rationAssList.length>0){
             for(let i=0;i<impactRation.rationAssList.length;i++){
                 let times = calculateTimes(impactRation.rationAssList[i]);
                 if(times!=0){
                     assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
                     assList.push({times:times,assRation:assRation})
                     adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
                     }
                 }
         }
         for(let i =0;i<gljList.length;i++ ){
             let r = await calculateQuantityPerGLJ(gljList[i],i,coeList,assList,adjustState,isMarkPriceAjust);
             result.glj_result.push(r);
         }

        if(isMarkPriceAjust==null){
            await ration_glj.bulkWrite(generateUpdateTasks(result.glj_result));
        }
         adjustState= _.sortByOrder(adjustState, ['index'], ['asc']);
         adjustState=_.map(adjustState, _.property('content'));
         let adjustStateString = adjustState.join(';');
         await ration.update({projectID:query.projectID,ID:query.rationID,deleteInfo: null},{adjustState:adjustStateString});
         result.adjustState=adjustStateString;
         return result;
    }catch (err){
        console.log(err);
        throw err;
    }
}

function generateUpdateTasks(result) {
    let tasks = [];
    for(let i =0;i<result.length;i++){
        let task= {
            updateOne: {
                filter: result[i].query,
                update: result[i].doc
            }
        }
        tasks.push(task);
    }
    return tasks;
}


async function calculateQuantityPerGLJ(glj,index,coeList,assList,adjustState,isMarkPriceAjust) {
    let quantity =  glj.quantity;
    let result={
        query:{
            ID:glj.ID,
            projectID:glj.projectID
        },
        doc:{
            quantity: quantity
        }
    };
    try {
        if(isMarkPriceAjust==null){
            if(!glj._doc.hasOwnProperty('customQuantity')||glj.customQuantity==null){
                quantity =glj.rationItemQuantity;
                quantity =calculateAss(quantity,assList,glj);
                quantity = calculateQuantityByCoes(quantity,coeList,glj);
            }else {
                quantity = glj.customQuantity;
                result.doc.customQuantity = glj.customQuantity;
            }
            let customerCoe = _.last(coeList);
            if(customerCoe.isAdjust==1){
                quantity = calculateQuantityByCustomerCoes(quantity,customerCoe,glj);
            }
            result.doc.quantity =_.round(quantity,3);
        }
        generateAdjustState(glj,coeList,adjustState,index);
        return result;
    }catch (err){
        throw err;
    }
}

function calculateAss(quantity,assList,glj) {
    for(let i=0;i<assList.length;i++){
        if(assList[i].assRation){
            let assglj = _.find(assList[i].assRation.rationGljList,function (aglj) {
                return aglj.gljId == glj.GLJID
            })
            if(assglj){
                let calQuantity = assglj.consumeAmt*assList[i].times;
                quantity += calQuantity
            }
        }
    }
    return quantity;
}

function generateAdjustState(glj,coeList,adjustState,index) {
   //替换工料机 and  添加工料机

    // to do

  //标准附注条件调整 + 自定义乘系数
    if(0==index){
        for(let i=0;i<coeList.length;i++){
            if(coeList[i].isAdjust==1){
                if(i==coeList.length-1){
                    adjustState.push({index:stateSeq.cusCoe,content:coeList[i].content});
                }else {
                    adjustState.push({index:stateSeq.coe,content:"调 : "+coeList[i].content});
                }
            }
        }
    }

    //自定义消耗量
    if(glj._doc.hasOwnProperty('customQuantity')){
        if(glj.customQuantity!==null){
            adjustState.push({index:stateSeq.cusQuantity,content:glj.code+'量'+glj.customQuantity});
        }
    }
    //市场单价调整
    if(glj._doc.hasOwnProperty('marketPriceAdjust')&&glj.marketPriceAdjust&&glj.marketPriceAdjust!=0){
        //0101005价66.00
        adjustState.push({index:stateSeq.adjMak,content:glj.code+'价'+glj.marketPriceAdjust});
    }

    return adjustState;
}


function calculateTimes(ass){
    let times =(ass.actualValue-ass.stdValue)/ass.stepValue;
    let r = false;
    if(times<0){
        r=true;
        times=times*-1;
    }
    if(ass.carryBit=='四舍五入'){
        times = _.round(times,ass.decimal);
    }else if (ass.carryBit=='进一'){
        times =_.ceil(times,ass.decimal);
    }
    if(r){
        times=times*-1;
    }
    return times;
}

function calculateQuantityByCoes(quantity,coeList,glj){
    let coeQuantity = quantity;
    if(coeList.length>1){
        for(let i=0;i<coeList.length-1;i++){
            coeQuantity = everyCoe(coeQuantity,coeList[i],glj);
        }
    }
    return coeQuantity;
}

function everyCoe(quantity,coe,glj) {
    let coeQuantity = quantity;
    if(coe.isAdjust==1){
        for(let i=0;i<coe.coes.length;i++){
            if(coe.coes[i].coeType=='单个'&&coe.coes[i].gljCode==glj.code){
                coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
            } else if(coe.coes[i].coeType=='定额'){
                coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
            }else if(coe.coes[i].coeType==getGLJTypeByID(glj.type)){
                coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
            }
        }
    }
    return coeQuantity;
}


function calculateQuantityByCustomerCoes(quantify,coe,glj) {
    let rationAmount = coe.coes[0].amount;
    if(_.every(coe.coes,'amount',rationAmount)){
        return getCalculateResult(quantify, coe.coes[0])
    }else {
        for(let i=1;i<coe.coes.length;i++){
            if(coe.coes[i].coeType.search(getGLJTypeByID(glj.type))!=-1){
                return getCalculateResult(quantify,coe.coes[i])
            }
        }
    }
    return quantify
}

function getCalculateResult(quantify,c) {
    let q = quantify;
    switch (c.operator){
        case '+' :
            q = q + c.amount;
            break;
        case '-' :
            q = q - c.amount;
            break;
        case '*' :
            q = q * c.amount;
            break;
        case '/' :
            q = q / c.amount;
            break;
        case '=' :
             q = c.amount;
            break;
    }
    return q;
}

function getGLJTypeByID(id) {
    let glj_type_object = glj_type_util.getStdGljTypeCacheObj();
    let topTypeId = glj_type_object.getTopParentIdByItemId(id);
    let type = glj_type_object.getItemById(topTypeId);
    if(type!=undefined){
        return type.fullName;
    }else {
        return '';
    }
}