package nc.bs.mmpac.pmo.pac0002.bp;

import java.util.ArrayList;
import java.util.List;
import nc.bs.mmpac.pmo.pac0002.pluginpoint.PMOPluginPoint;
import nc.bs.mmpac.pmo.pac0002.rule.PMOATOCheckRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOATPUpdateRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOCffileidInserAndUpdatetRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOCreatePickmWhenInsertRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOInsertSaveApproveRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOMarkWrSNWhenInsertRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOSNDupCheckRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOSaveSNWhenInsertRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOSplitByTaskDetailsRule;
import nc.bs.mmpac.pmo.pac0002.rule.PMOSyncSNWhenInsertRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.CheckMaterialIsEnableRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckCinwarehouseidRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckDMODuplicateRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckDateLogicRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckMaterialPermissionRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckNrwxisLogicRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckParentStatusRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckProcedureDateLogicRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckProcedureDupRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckProcedurePSCRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckProcedureratioRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckProdurepointRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckSCDuplicateRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckSNNumAndUnitRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOCheckSaveNotNullRule;
import nc.bs.mmpac.pmo.pac0002.rule.check.PMOProcedureChkPntRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillBatchCodeRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillFirstMOInfoRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillInsertBatchValueRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillInsertDefaultValueRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillInsertPlanTimeByProcedureRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillMaterialRelationRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillPushDefaultValueRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillPushVersionRule;
import nc.bs.mmpac.pmo.pac0002.rule.fill.PMOFillSNPkAndCodeRule;
import nc.bs.mmpac.pmo.pac0002.rule.grand.PMOCreatePlanOutputRule;
import nc.bs.mmpac.pmo.pac0002.rule.grand.PMOCreateProcedureRule;
import nc.bs.mmpac.pmo.pac0002.rule.grand.PMOSyncPlanmmNumRule;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4MPS;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4PMO;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4PSCRecive;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4PSM;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4Renovate;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4SFC;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4SO;
import nc.bs.mmpac.pmo.pac0002.rule.rewrite.RewriteInsertNum4TO;
import nc.bs.mmpac.pmo.pac0002.bp.rule.saveBeforeCheckRule;
import nc.bs.mmpub.rule.MMATOMaterialCheckRule;
import nc.bs.mmpub.rule.MMAutoMaterialAssignRule;
import nc.bs.mmpub.rule.MMBillTypeIsLockCheckRule;
import nc.bs.pubapp.pub.rule.FieldLengthCheckRule;
import nc.bs.pubapp.pub.rule.FillInsertDataRule;
import nc.bs.pubapp.pub.rule.OrgDisabledCheckRule;
import nc.impl.pubapp.bd.userdef.UserDefSaveRule;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.impl.pubapp.pattern.rule.processer.AroundProcesser;
import nc.pubitf.sn.doc.param.SnDocParam;
import nc.util.mmf.busi.rule.MMBillCodeCheckAndTrantypeRule;
import nc.util.mmf.busi.rule.MMCheckMaterialProdModeRule;
import nc.util.mmf.busi.rule.MMCheckMaterialVirtualRule;
import nc.util.mmf.busi.rule.MMCreateBillcodeAndTrantypecodeRule;
import nc.util.mmf.busi.rule.MMRowNoCheckRule;
import nc.util.mmf.framework.gc.GCBillCloneUtil;
import nc.util.mmf.framework.gc.GCBillInsert;
import nc.util.mmf.framework.gc.GCInsertBPTemplate;
import nc.vo.mmpac.pmo.pac0002.entity.PMOAggVO;
import nc.vo.mmpac.pmo.pac0002.util.PmoSagaUtil;

public class PMOInsertBP {
	public PMOAggVO[] insert(PMOAggVO[] bills, boolean issub, boolean isPush) {
		AroundProcesser<PMOAggVO> processer = new AroundProcesser<PMOAggVO>(PMOPluginPoint.INSERT);
		List<SnDocParam> updateParams = new ArrayList<SnDocParam>();
		List<SnDocParam> saveParams = new ArrayList<SnDocParam>();

		addBeforeRule(processer, issub, isPush, updateParams, saveParams);

		addAfterRule(processer, issub, isPush, updateParams, saveParams);
		GCBillInsert<PMOAggVO> bo = new GCBillInsert<PMOAggVO>();
		PMOAggVO[] aggvos = (PMOAggVO[]) processer.before(bills);
		PMOAggVO[] newvos = (PMOAggVO[]) bo.insert(aggvos);

		PmoSagaUtil.addSagaAndCompensate4Insert(newvos);
		return (PMOAggVO[]) processer.after(newvos);
	}

	public void insertSagasCheck(PMOAggVO[] bills, boolean issub, boolean isPush) {
		GCInsertBPTemplate<PMOAggVO> bp = new GCInsertBPTemplate<PMOAggVO>(PMOPluginPoint.INSERT);

		addBeforeRuleSagasCheck(bp.getAroundProcesser(), issub, isPush);
		bp.getAroundProcesser().before(bills);
	}

	private void addBeforeRule(AroundProcesser<PMOAggVO> processer, boolean issub, boolean isPush,
			List<SnDocParam> updateParams, List<SnDocParam> saveParams) {
		IRule<PMOAggVO> materialIsEnableRule = new CheckMaterialIsEnableRule();
		processer.addBeforeRule(materialIsEnableRule);

		OrgDisabledCheckRule orgDisabledCheckRule = new OrgDisabledCheckRule("pk_org", "FACTORYTYPE000000000");
		processer.addBeforeRule(orgDisabledCheckRule);

		FillInsertDataRule fillInsertDataRule = new FillInsertDataRule();
		processer.addBeforeRule(fillInsertDataRule);

		MMBillTypeIsLockCheckRule mMBillTypeIsLockCheckRule = new MMBillTypeIsLockCheckRule("vtrantypecode");
		processer.addBeforeRule(mMBillTypeIsLockCheckRule);

		MMAutoMaterialAssignRule mMAutoMaterialAssignRule = new MMAutoMaterialAssignRule(null, "cmaterialvid",
				new String[] { "pk_org", "cplanfactoryid" }, null);

		processer.addBeforeFinalRule(mMAutoMaterialAssignRule);

		MMATOMaterialCheckRule mMATOMaterialCheckRule = new MMATOMaterialCheckRule(null, "cmaterialvid", "cffileid");

		processer.addBeforeRule(mMATOMaterialCheckRule);

		IRule<PMOAggVO> marperrule = new PMOCheckMaterialPermissionRule();
		processer.addBeforeRule(marperrule);

		MMCheckMaterialVirtualRule mMCheckMaterialVirtualRule = new MMCheckMaterialVirtualRule();
		processer.addBeforeRule(mMCheckMaterialVirtualRule);

		IRule<PMOAggVO> chkrwxisrule = new PMOCheckNrwxisLogicRule();
		processer.addBeforeRule(chkrwxisrule);

		IRule<PMOAggVO> chkrule = new PMOCheckSaveNotNullRule(issub);
		processer.addBeforeRule(chkrule);

		IRule<PMOAggVO> fillvaluerule = new PMOFillInsertDefaultValueRule();
		processer.addBeforeRule(fillvaluerule);

		processer.addBeforeRule(new PMOSyncPlanmmNumRule());

		MMRowNoCheckRule mMRowNoCheckRule = new MMRowNoCheckRule();
		processer.addBeforeRule(mMRowNoCheckRule);

		IRule<PMOAggVO> scrapAddrule = new PMOCheckParentStatusRule();
		processer.addBeforeRule(scrapAddrule);

		IRule<PMOAggVO> snDuprule = new PMOSNDupCheckRule();
		processer.addBeforeRule(snDuprule);

		IRule<PMOAggVO> outputrule = new PMOCreatePlanOutputRule();
		processer.addBeforeRule(outputrule);

		IRule<PMOAggVO> procedurerule = new PMOCreateProcedureRule(isPush);
		processer.addBeforeRule(procedurerule);

		IRule<PMOAggVO> filltimeprocedurerule = new PMOFillInsertPlanTimeByProcedureRule();
		processer.addBeforeRule(filltimeprocedurerule);

		IRule<PMOAggVO> daterule = new PMOCheckDateLogicRule();
		processer.addBeforeRule(daterule);

		IRule<PMOAggVO> chkPntRule = new PMOProcedureChkPntRule();
		processer.addBeforeRule(chkPntRule);

		processer.addBeforeRule(new PMOCheckProdurepointRule());

		IRule<PMOAggVO> procdatelogicrule = new PMOCheckProcedureDateLogicRule(true);
		processer.addBeforeRule(procdatelogicrule);

		IRule<PMOAggVO> proccoderule = new PMOCheckProcedureDupRule();
		processer.addBeforeRule(proccoderule);

		IRule<PMOAggVO> procPscCheckRule = new PMOCheckProcedurePSCRule();
		processer.addBeforeRule(procPscCheckRule);

		FieldLengthCheckRule fieldLengthCheckRule = new FieldLengthCheckRule();
		processer.addBeforeRule(fieldLengthCheckRule);

		UserDefSaveRule<PMOAggVO> defRule = new UserDefSaveRule<PMOAggVO>(
				new Class[] { nc.vo.mmpac.pmo.pac0002.entity.PMOItemVO.class });
		processer.addBeforeRule(defRule);

		MMCheckMaterialProdModeRule<PMOAggVO> prodModeRule = new MMCheckMaterialProdModeRule<PMOAggVO>(1,
				nc.vo.mmpac.pmo.pac0002.entity.PMOItemVO.class);

		processer.addBeforeRule(prodModeRule);

		IRule<PMOAggVO> rewriteReviceRule = new RewriteInsertNum4PSCRecive();
		processer.addBeforeRule(rewriteReviceRule);

		IRule<PMOAggVO> wrMarkRule = new PMOMarkWrSNWhenInsertRule();
		processer.addBeforeRule(wrMarkRule);

		IRule<PMOAggVO> atprule = new PMOATPUpdateRule(true, "55A2");
		processer.addBeforeRule(atprule);

		IRule<PMOAggVO> rewritewr = new RewriteInsertNum4Renovate();
		processer.addBeforeRule(rewritewr);

		IRule<PMOAggVO> rewritesfc = new RewriteInsertNum4SFC();
		processer.addBeforeRule(rewritesfc);

		MMCreateBillcodeAndTrantypecodeRule mMCreateBillcodeAndTrantypecodeRule = new MMCreateBillcodeAndTrantypecodeRule(
				"55A2", "vbillcode", "pk_group", "pk_org", "vtrantypecode");

		processer.addBeforeRule(mMCreateBillcodeAndTrantypecodeRule);

		IRule<PMOAggVO> fillfirstInfo = new PMOFillFirstMOInfoRule();
		processer.addBeforeRule(fillfirstInfo);

		IRule<PMOAggVO> fillbatchvaluerule = new PMOFillInsertBatchValueRule();
		processer.addBeforeRule(fillbatchvaluerule);

		IRule<PMOAggVO> batchcodeRule = new PMOFillBatchCodeRule();
		processer.addBeforeRule(batchcodeRule);

		PMOCffileidInserAndUpdatetRule cffileidRule = new PMOCffileidInserAndUpdatetRule();
		processer.addBeforeRule(cffileidRule);

		IRule<PMOAggVO> snCheckRule = new PMOCheckSNNumAndUnitRule();
		processer.addBeforeRule(snCheckRule);

		IRule<PMOAggVO> snRule = new PMOFillSNPkAndCodeRule();
		processer.addBeforeRule(snRule);

		IRule<PMOAggVO> snSyncRule = new PMOSyncSNWhenInsertRule(updateParams, saveParams);
		processer.addBeforeRule(snSyncRule);

		IRule<PMOAggVO> checkCinwarehouseidRule = new PMOCheckCinwarehouseidRule();
		processer.addBeforeRule(checkCinwarehouseidRule);

		IRule<PMOAggVO> atoCheck = new PMOATOCheckRule();
		processer.addBeforeRule(atoCheck);

		IRule<PMOAggVO> procedureIRule = new PMOCheckProcedureratioRule();
		processer.addBeforeRule(procedureIRule);
		
		IRule<PMOAggVO> saveBeforeCheckRule = new saveBeforeCheckRule();
        processer.addBeforeRule(saveBeforeCheckRule);
	}

	private void addBeforeRuleSagasCheck(AroundProcesser<PMOAggVO> processer, boolean issub, boolean isPush) {
		OrgDisabledCheckRule orgDisabledCheckRule = new OrgDisabledCheckRule("pk_org", "FACTORYTYPE000000000");
		processer.addBeforeRule(orgDisabledCheckRule);

		FillInsertDataRule fillInsertDataRule = new FillInsertDataRule();
		processer.addBeforeRule(fillInsertDataRule);

		MMBillTypeIsLockCheckRule mMBillTypeIsLockCheckRule = new MMBillTypeIsLockCheckRule("vtrantypecode");
		processer.addBeforeRule(mMBillTypeIsLockCheckRule);

		MMATOMaterialCheckRule mMATOMaterialCheckRule = new MMATOMaterialCheckRule(null, "cmaterialvid", "cffileid");

		processer.addBeforeRule(mMATOMaterialCheckRule);

		IRule<PMOAggVO> marperrule = new PMOCheckMaterialPermissionRule();
		processer.addBeforeRule(marperrule);

		MMCheckMaterialVirtualRule mMCheckMaterialVirtualRule = new MMCheckMaterialVirtualRule();
		processer.addBeforeRule(mMCheckMaterialVirtualRule);

		IRule<PMOAggVO> chkrwxisrule = new PMOCheckNrwxisLogicRule();
		processer.addBeforeRule(chkrwxisrule);

		IRule<PMOAggVO> chkrule = new PMOCheckSaveNotNullRule(issub);
		processer.addBeforeRule(chkrule);

		IRule<PMOAggVO> fillvaluerule = new PMOFillInsertDefaultValueRule();
		processer.addBeforeRule(fillvaluerule);

		processer.addBeforeRule(new PMOSyncPlanmmNumRule());

		MMRowNoCheckRule mMRowNoCheckRule = new MMRowNoCheckRule();
		processer.addBeforeRule(mMRowNoCheckRule);

		IRule<PMOAggVO> daterule = new PMOCheckDateLogicRule();
		processer.addBeforeRule(daterule);

		IRule<PMOAggVO> chkPntRule = new PMOProcedureChkPntRule();
		processer.addBeforeRule(chkPntRule);

		processer.addBeforeRule(new PMOCheckProdurepointRule());

		IRule<PMOAggVO> procdatelogicrule = new PMOCheckProcedureDateLogicRule(true);
		processer.addBeforeRule(procdatelogicrule);

		IRule<PMOAggVO> proccoderule = new PMOCheckProcedureDupRule();
		processer.addBeforeRule(proccoderule);

		FieldLengthCheckRule fieldLengthCheckRule = new FieldLengthCheckRule();
		processer.addBeforeRule(fieldLengthCheckRule);

		UserDefSaveRule<PMOAggVO> defRule = new UserDefSaveRule<PMOAggVO>(
				new Class[] { nc.vo.mmpac.pmo.pac0002.entity.PMOItemVO.class });
		processer.addBeforeRule(defRule);

		MMCheckMaterialProdModeRule<PMOAggVO> prodModeRule = new MMCheckMaterialProdModeRule<PMOAggVO>(1,
				nc.vo.mmpac.pmo.pac0002.entity.PMOItemVO.class);

		processer.addBeforeRule(prodModeRule);

		IRule<PMOAggVO> snCheckRule = new PMOCheckSNNumAndUnitRule();
		processer.addBeforeRule(snCheckRule);

		IRule<PMOAggVO> atoCheck = new PMOATOCheckRule();
		processer.addBeforeRule(atoCheck);
	}

	private void addAfterRule(AroundProcesser<PMOAggVO> processer, boolean issub, boolean isPush,
			List<SnDocParam> updateParams, List<SnDocParam> saveParams) {
		MMBillCodeCheckAndTrantypeRule mMBillCodeCheckAndTrantypeRule = new MMBillCodeCheckAndTrantypeRule("55A2",
				"vbillcode", "pk_group", "pk_org", "vtrantypecode");

		processer.addAfterRule(mMBillCodeCheckAndTrantypeRule);

		IRule<PMOAggVO> duprule = new PMOCheckSCDuplicateRule();
		processer.addAfterRule(duprule);

		IRule<PMOAggVO> dmoduprule = new PMOCheckDMODuplicateRule();
		processer.addAfterRule(dmoduprule);

		IRule<PMOAggVO> pmorule = new RewriteInsertNum4PMO();
		processer.addAfterRule(pmorule);

		IRule<PMOAggVO> rewriteso = new RewriteInsertNum4SO();
		processer.addAfterRule(rewriteso);

		IRule<PMOAggVO> rewritepsm = new RewriteInsertNum4PSM();
		processer.addAfterRule(rewritepsm);

		IRule<PMOAggVO> rewritepo = new RewriteInsertNum4MPS();
		processer.addAfterRule(rewritepo);

		IRule<PMOAggVO> rewriteto = new RewriteInsertNum4TO();
		processer.addAfterRule(rewriteto);

		IRule<PMOAggVO> atprule = new PMOATPUpdateRule(false, "55A2");
		processer.addAfterRule(atprule);

		IRule<PMOAggVO> snsaverule = new PMOSaveSNWhenInsertRule(updateParams, saveParams);
		processer.addAfterRule(snsaverule);

		IRule<PMOAggVO> createPickmRule = new PMOCreatePickmWhenInsertRule();
		processer.addAfterRule(createPickmRule);

		IRule<PMOAggVO> saveapproverule = new PMOInsertSaveApproveRule();
		processer.addAfterRule(saveapproverule);
	}

	public PMOAggVO[] pushInsert(PMOAggVO[] vos, boolean issub, String pushtype) {
		AroundProcesser<PMOAggVO> processer = new AroundProcesser<PMOAggVO>(PMOPluginPoint.PUSHINSERT);

		addPushInsertBeforeRules(processer, pushtype);
		processer.before(vos);

		PMOAggVO[] aggvos = insert(vos, issub, true);
		if ("PSM".equals(pushtype)) {
			PMOAggVO[] cloneVos = (PMOAggVO[]) (new GCBillCloneUtil()).cloneBills(aggvos);

			PMOSplitByTaskDetailsRule createPutPlan = new PMOSplitByTaskDetailsRule(false);
			createPutPlan.process(cloneVos);
		}
		return aggvos;
	}

	public void pushInsertSagasCheck(PMOAggVO[] vos, boolean issub, String pushtype) {
		AroundProcesser<PMOAggVO> processer = new AroundProcesser<PMOAggVO>(PMOPluginPoint.PUSHINSERT);

		addPushInsertBeforeRules(processer, pushtype);
		processer.before(vos);

		insertSagasCheck(vos, issub, true);
	}

	private void addPushInsertBeforeRules(AroundProcesser<PMOAggVO> processer, String pushtype) {
		IRule<PMOAggVO> versionrule = new PMOFillPushVersionRule();
		processer.addBeforeRule(versionrule);

		IRule<PMOAggVO> defaultrule = new PMOFillPushDefaultValueRule();
		processer.addBeforeRule(defaultrule);

		IRule<PMOAggVO> relationrule = new PMOFillMaterialRelationRule(pushtype);
		processer.addBeforeRule(relationrule);
	}
}
