package com.xisc.pm.app.service.autoboard.core;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Queue;

import com.xisc.pm.api.dto.PmProContYieldResposeDTO;
import com.xisc.pm.app.service.autoboard.config.CalcLog;
import com.xisc.pm.app.service.autoboard.dto.PmAutoBoardExecParam;
import com.xisc.pm.app.service.autoboard.dto.PmAutoBoardExecResult;
import com.xisc.pm.app.service.autoboard.dto.PmAutoBoardPolicyGroupDTO;
import com.xisc.pm.app.service.autoboard.dto.PmAutoPdLog;
import com.xisc.pm.app.service.autoboard.dto.PmContBoardParam;
import com.xisc.pm.app.service.autoboard.dto.PmPdResultDTO;
import com.xisc.pm.infra.enums.FormPlateMode;

/**
 * 组板程序（A）
 * 1. 长度接近极限长，优先组板
 * 2. 按队列顺序依次组板。依次减少1块小板，直到能组板成功，如果组板失败，移除第一个合同。
 * 
 * @author jun.zeng
 *
 */
public class PmPdProgramA extends DefaultPmPdProgram {

    private Deque<PmContBoardParam> priorityQueue;
    private PmAutoBoardExecResult execResult;
    private PmAutoBoardExecParam current;
    private PmAutoBoardPolicyGroupDTO policyGroup;
    private FormPlateMode formPlateMode;
     

    public PmPdProgramA(Queue<PmContBoardParam> priorityQueue, PmAutoBoardExecResult execResult,
            PmAutoBoardExecParam current, PmAutoBoardPolicyGroupDTO policyGroup, FormPlateMode formPlateMode) {
        this.current = current;
        this.priorityQueue = (Deque<PmContBoardParam>) priorityQueue;
        this.execResult = execResult;
        this.policyGroup = policyGroup;
        this.formPlateMode = formPlateMode;
    }

    @Override
    public Boolean call() throws Exception {
        // 正在组板标记
        boolean doPdFlag = false;
        PmContBoardParam axisPmContBoardParam = null;
        BigDecimal szWid = BigDecimal.ZERO;
        BigDecimal szLen = BigDecimal.ZERO;
        BigDecimal allWt = BigDecimal.ZERO;
        BigDecimal spCount = BigDecimal.ZERO;
        List<BigDecimal> lens = new ArrayList<>();
        List<String> block1 = new ArrayList<>();
        // 组板中的集合
        List<PmContBoardParam> pmContBoardParams = new ArrayList<>();
        // 
        while (!priorityQueue.isEmpty()) {
            PmContBoardParam pmContBoardParam = priorityQueue.peek();
            BigDecimal qty = execResult.calcRemainingPdQty(pmContBoardParam);
            if (BigDecimal.ZERO.compareTo(qty) >= 0) {
                priorityQueue.poll();
                continue;
            }
            if (!doPdFlag) {
                doPdFlag = true;
                axisPmContBoardParam = pmContBoardParam;
                szLen = BigDecimal.ZERO;
                spCount = BigDecimal.ZERO;
                allWt = BigDecimal.ZERO;
                lens.clear();
                block1.clear();
            }
            BigDecimal tmpRemainLen = policyGroup.getMaxCombinePlateLen().subtract(szLen);
            BigDecimal quotient = tmpRemainLen.divide(pmContBoardParam.getSmallPlateLen(), 0, RoundingMode.DOWN); // 整除
            
            boolean a2WidDeviationFlag = true ;
            if(pmContBoardParams.size() > 1) {
                // 上一个合同
//                PmContBoardParam tmp = pmContBoardParams.get(pmContBoardParams.size() - 1);
                PmContBoardParam tmp = axisPmContBoardParam;
                if(formPlateMode == FormPlateMode.A2 &&
                        current.getPolicy().getA2WidDeviation() != null 
                        && tmp.getOrderWid().subtract(pmContBoardParam.getOrderWid()).compareTo(current.getPolicy().getA2WidDeviation()) >= 0) {
                    a2WidDeviationFlag = false ;
                }
            }
            boolean calcFlag = false ;
            if (quotient.compareTo(qty) > 0 && a2WidDeviationFlag) {
                // 如果当前合同剩余数量未达到最大组板长度，合同出队列。全部加到待组板队列中
                spCount = spCount.add(qty);
                szWid = axisPmContBoardParam.getOrderWid();
                szLen = szLen.add(pmContBoardParam.getSmallPlateLen().multiply(qty));
                allWt = allWt.add(pmContBoardParam.getOrderUnitAim().multiply(qty));
                for (BigDecimal i = qty; i.compareTo(BigDecimal.ZERO) > 0; i = i.subtract(BigDecimal.ONE)) {
                    lens.add(pmContBoardParam.getSmallPlateLen());
                    block1.add(pmContBoardParam.getOrderNo());
                }
                pmContBoardParams.add(pmContBoardParam);
                priorityQueue.poll();
                if(priorityQueue.isEmpty()) {
                    calcFlag = true ;
                    quotient = qty;
                }
            } else {
                // 如果剩余数量满足需求，数量增加
                if(quotient.compareTo(BigDecimal.ZERO) > 0 && a2WidDeviationFlag) {
                    spCount = spCount.add(quotient);
                    szWid = axisPmContBoardParam.getOrderWid();
                    szLen = szLen.add(pmContBoardParam.getSmallPlateLen().multiply(quotient));
                    allWt = allWt.add(pmContBoardParam.getOrderUnitAim().multiply(quotient));
                    pmContBoardParams.add(pmContBoardParam);
                    for (BigDecimal i = quotient; i.compareTo(BigDecimal.ZERO) > 0; i = i.subtract(BigDecimal.ONE)) {
                        lens.add(pmContBoardParam.getSmallPlateLen());
                        block1.add(pmContBoardParam.getOrderNo());
                    }
                } else {
                    pmContBoardParam = pmContBoardParams.get(pmContBoardParams.size() - 1);
                    quotient = execResult.calcRemainingPdQty(pmContBoardParam);
                }
                calcFlag = true ;
            }
            if(calcFlag) {
                BigDecimal i = quotient;
                p: do {
                    
                    PmProContYieldResposeDTO respose = checkResult(formPlateMode, pmContBoardParams, policyGroup, current, execResult, szWid, szLen,
                            axisPmContBoardParam, lens, allWt , block1 , null);
                    
                    if (respose != null) {
                        // 如果能组板。记录组板结果；
                        PmPdResultDTO pmPdResult = new PmPdResultDTO(szLen, szWid, spCount, allWt, lens, pmContBoardParams
                                , formPlateMode.getCode(), block1, null , axisPmContBoardParam);
                        pmPdResult.setRespose(respose);
                        pmPdResult.setCurrent(current);
                        if(respose.getTransFlag() != null) {
                            pmPdResult.setTransFlag(respose.getTransFlag());
                        }
                        try {
                            boolean canExecFlag = execResult.addVirtualSlab(pmPdResult);
                            if(!canExecFlag) {
                                return false;
                            }
                            BigDecimal firstRemainQty = execResult.calcRemainingPdQty(axisPmContBoardParam);
                            if(firstRemainQty.compareTo(BigDecimal.ZERO) > 0 && !priorityQueue.isEmpty() 
                                    && !priorityQueue.peekFirst().getOrderNo().equals(axisPmContBoardParam.getOrderNo())) {
                                priorityQueue.offerFirst(axisPmContBoardParam);
                            }
                        } catch (Exception e) {
                            CalcLog.log("组板失败："+e.getMessage());
                            CalcLog.log(new PmAutoPdLog(current.getRequestId(), execResult.getVersion() , current.getMoldId()).setAxisOrderNo(axisPmContBoardParam.getOrderNo()).setBlock1(block1).setBlock2(null)
                                    .setFormPlateMode(formPlateMode.getCode()).setLens(lens).setMessage("组板失败："+e.getMessage()));
                        }
                        doPdFlag = false;
                        pmContBoardParams.clear();
                        
                        break p;
                    }
                    i = i.subtract(BigDecimal.ONE);
                    szLen = szLen.subtract(pmContBoardParam.getSmallPlateLen());
                    allWt = allWt.subtract(pmContBoardParam.getOrderUnitAim());
                    spCount = spCount.subtract(BigDecimal.ONE);
                    if(spCount.compareTo(BigDecimal.ONE) < 0) {
                        doPdFlag = false ;
                        pmContBoardParams.clear();
                        if(!priorityQueue.isEmpty()) {
                            PmContBoardParam pmContBoardParamFirst = priorityQueue.peek();
                            if(pmContBoardParamFirst.getOrderNo().equals(axisPmContBoardParam.getOrderNo())) {
                                priorityQueue.poll();
                            }
                        }
                        break p; 
                    }
                    lens.remove(spCount.intValue());
                    block1.remove(spCount.intValue());

                    if(i.compareTo(BigDecimal.ZERO) == 0) {
                        pmContBoardParams.remove(pmContBoardParams.size() - 1);
                        PmContBoardParam queueFirst = priorityQueue.peek();
                        if(pmContBoardParams.size() > 0 && queueFirst != null && !pmContBoardParam.getOrderNo().equals(queueFirst.getOrderNo())) {
                            // 如果组板数组只剩一个合同，最后一个合同不入队列
                            priorityQueue.offerFirst(pmContBoardParam);
                        } 
                        if(pmContBoardParams.size() == 0) {
                            doPdFlag = false ;
                        }
                        pmContBoardParam = pmContBoardParams.get(pmContBoardParams.size() - 1);
                        i = execResult.calcRemainingPdQty(pmContBoardParam);
                    }
                } while(doPdFlag && pmContBoardParams.size() >= 1);
                
            }

        }
        return true;
    }

}
