package com.gx.obe.management.thread;

import java.math.BigDecimal;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.eclipse.swt.core.CallBack;

import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
import com.gx.obe.formula.AvgFloatRangeItem;
import com.gx.obe.formula.BasePriceRangeParam;
import com.gx.obe.formula.BenchmarkPriceParam;
import com.gx.obe.formula.CalculationParam;
import com.gx.obe.formula.DeviateRateItem;
import com.gx.obe.formula.FilterCountConditionItem;
import com.gx.obe.formula.PriceParam;
import com.gx.obe.formula.SpecimenFilterConditionItem;
import com.gx.obe.message.Messages;
import com.gx.obe.util.utils.BigDecimalUtils;
import com.gx.obe.util.utils.ObjectUtils;
import com.gx.obe.util.utils.StringUtils;
import com.gx.obe.util.utils.XmlUtils;
import com.gx.obe.web.entity.evaluation.EvaluationFactor;
import com.gx.obe.web.entity.tender.TenderProjectEntity;
import com.gx.obe.web.service.evaluation.EvaluationFactorService;

public class NewExportEvaluationFactorThread implements Runnable {
	
	private EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
	private Thread thread;
	private TenderProjectEntity tenderProjectEntity;
	private String saveFilePath;
	private CallBack callBack;
	private int factorNum;

	public NewExportEvaluationFactorThread(TenderProjectEntity tenderProjectEntity, String saveFilePath, CallBack callBack) {
		this.tenderProjectEntity = tenderProjectEntity;
		this.saveFilePath = saveFilePath;
		this.callBack = callBack;
	}
	
	public void run() {
		//创建Document对象
		Document document = DocumentHelper.createDocument();
		//创建packEvalFactors根节点
		Element packEvalFactors = document.addElement("packEvalFactors");
		packEvalFactors.addElement("PackId").setText(tenderProjectEntity.getId());
		packEvalFactors.addElement("packCode").setText(tenderProjectEntity.getTenderNo());
		packEvalFactors.addElement("packName").setText(tenderProjectEntity.getTenderName());
		//创建符合性评审指标标签<complianceFactors>
		Element complianceFactors = packEvalFactors.addElement("complianceFactors");
		//创建打分评审指标标签<scoreFactors>
		Element scoreFactors = packEvalFactors.addElement("scoreFactors");
		//创建价格评审指标标签<priceFactors>
		Element priceFactors = packEvalFactors.addElement("priceFactors");
		
		createPrelimaryOrDetailFactorItem(complianceFactors, Messages.Factor_compliance, EvaluationFactorEnum.AUDIT_COMPLIANCE);
		createPrelimaryOrDetailFactorItem(scoreFactors, Messages.Factor_score, EvaluationFactorEnum.AUDIT_SCORE);
		
		callBackMsg("正在读取【价格指标】...");
		// 获得价格指标
//		EvaluationFactor priceFactor = evaluationFactorService.getPriceEvaluationFactor(tenderProjectEntity.getId());
		List<EvaluationFactor> priceFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProjectEntity.getId(),EvaluationFactorEnum.AUDIT_PRICE);
		if(null != priceFactorList && priceFactorList.size() > 0) {
			for(EvaluationFactor priceFactor : priceFactorList) {
				if(null != priceFactor){
					++factorNum;
					createFactorItem(priceFactors, priceFactor);
				}else{
					callBackMsg("×未检测到有效的【价格指标】！");
				}
			}
		}
		//生成EvaluationFactor.xml文件
		if(factorNum > 0){
			// 创建xml文件
			if(XmlUtils.createXmlFile(document, saveFilePath, "UTF-8")){
				callBackMsg("√导出评审指标成功！");
			}else {
				callBackMsg("×导出评审指标失败！");
			}
		}
		callBackMsg("导出评审指标结束！");
		if(null != callBack){
			callBack.after();
		}
	}
	
	private void createPrelimaryOrDetailFactorItem(Element element, String factorName, String auditType) {
		callBackMsg("正在读取【"+factorName+"】...");
		// 根据评审类型，获得评审指标集合
		List<EvaluationFactor> evalFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProjectEntity.getId(), auditType);
		if(null != evalFactorList && evalFactorList.size() > 0){
			for (EvaluationFactor evaluationFactor : evalFactorList) {
				++factorNum;
				createFactorItem(element, evaluationFactor);
			}
		}else{
			callBackMsg("×未检测到有效的【"+factorName+"】！");
		}
		if(auditType.equals(EvaluationFactorEnum.AUDIT_SCORE)){
			List<EvaluationFactor> creditFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProjectEntity.getId(), EvaluationFactorEnum.AUDIT_CREDIT);
			if(null != creditFactorList && creditFactorList.size() > 0){
				for (EvaluationFactor evaluationFactor : creditFactorList) {
					++factorNum;
					createFactorItem(element, evaluationFactor);
				}
			}
		}
	}

	private void createFactorItem(Element element, EvaluationFactor evaluationFactor) {
		callBackMsg("正在创建【"+evaluationFactor.getFactorName()+"】...");
		Element factor = element.addElement("factor");
//		Element factor = XmlBeanUtils.objectToElement(evaluationFactor, "factor");
		factor.addElement("options");
		Element childFactorList = factor.addElement("childFactorList");
		List<EvaluationFactor> evalFactorList = evaluationFactor.getChildFactorList();
		if (null != evalFactorList && evalFactorList.size() >0) {
			for (EvaluationFactor evaluationFactor2 : evalFactorList) {
				++factorNum;
				createFactorItem(childFactorList, evaluationFactor2);
			}
		}
		factor.addElement("id").setText(ObjectUtils.getObjString(evaluationFactor.getId()));
		if (!StringUtils.isEmpty(evaluationFactor.getParentId())) {
			factor.addElement("pid").setText(ObjectUtils.getObjString(evaluationFactor.getParentId()));
		}
		factor.addElement("code").setText(ObjectUtils.getObjString(evaluationFactor.getFactorCode()));
		factor.addElement("name").setText(ObjectUtils.getObjString(evaluationFactor.getFactorName()));
		factor.addElement("scoreType").setText(ObjectUtils.getObjString(evaluationFactor.getScoreType()));
		factor.addElement("evalBidType").setText(ObjectUtils.getObjString(evaluationFactor.getEvalBidType()));
		factor.addElement("evalGroup").setText(ObjectUtils.getObjString(evaluationFactor.getEvalGroup()));
		factor.addElement("score").setText(ObjectUtils.getObjString(evaluationFactor.getFactorScore()));
		factor.addElement("minScore").setText(ObjectUtils.getObjString(evaluationFactor.getFactorMinScore()));
		factor.addElement("maxScore").setText(ObjectUtils.getObjString(evaluationFactor.getFactorMaxScore()));
		factor.addElement("weight").setText(ObjectUtils.getObjString(evaluationFactor.getFactorWeight()));
		factor.addElement("isNeed");
		factor.addElement("evalContent");
		factor.addElement("objective");
		factor.addElement("containId");
		factor.addElement("factorType").setText(ObjectUtils.getObjString(evaluationFactor.getFactorType()));
		factor.addElement("memo").setText(ObjectUtils.getObjString(evaluationFactor.getMemo()));
		factor.addElement("isLeaf");
		factor.addElement("level");
		factor.addElement("scoreStatus").setText(ObjectUtils.getObjString(evaluationFactor.getScoreStatus()));
		
		//价格公式
		if(null != evaluationFactor.getComputerParams()) {
			PriceParam priceParam = PriceParam.deserializePriceParam(evaluationFactor.getComputerParams());
			if (null != priceParam) {
				//添加公式描述
				factor.addElement("remarks").setText(priceParam.getFormula());
				//添加公式
				Element priceFormulaElement = factor.addElement("priceFormula");
				
				BasePriceRangeParam specimenParam = priceParam.getSpecimenParam();
				BenchmarkPriceParam basePriceParam = priceParam.getBasePriceParam();
				CalculationParam calculationParam = priceParam.getCalculationParam();
				
				//基准价范围
				if(null != specimenParam) {
					Element specimenRangeElement = priceFormulaElement.addElement("specimenRange");
					specimenRangeElement.addElement("specimenType").setText(ObjectUtils.getObjString(specimenParam.getSpecimenType()));
					if(BasePriceRangeParam.SPECIMEN_TYPE_COUNT.equals(specimenParam.getSpecimenType())){
						//数量
						Element countElement = specimenRangeElement.addElement("count");
						countElement.addElement("defaultScore").setText(ObjectUtils.getObjString(specimenParam.getPriceScore()));
						Element countListElement = countElement.addElement("conditionList");
						List<FilterCountConditionItem> conditionItemList  = specimenParam.getFilterCountConditionList();
						if(null != conditionItemList && conditionItemList.size() > 0) {
							for(FilterCountConditionItem  conditionItem : conditionItemList) {
								Element conditionElement = countListElement.addElement("condition");
								if(conditionItem.isInclude()) {
									conditionElement.addElement("include").setText("01");
								}
								conditionElement.addElement("morethanCount").setText(conditionItem.getMorethanCount()+"");
								conditionElement.addElement("filterHighest").setText(conditionItem.getFilterHighest()+"");
								conditionElement.addElement("filterLowest").setText(conditionItem.getFilterLowest()+"");
							}
						}
						
					}else if(BasePriceRangeParam.SPECIMEN_TYPE_DISPERSION.equals(specimenParam.getSpecimenType())){
						//离散度
						Element dispersionElement = specimenRangeElement.addElement("dispersion");
						dispersionElement.addElement("defaultScore").setText(ObjectUtils.getObjString(specimenParam.getPriceScore()));
						dispersionElement.addElement("supplierNum").setText(specimenParam.getSupplierNum()+"");
						dispersionElement.addElement("higherSecondPercent").setText(specimenParam.getHeigerSecondPercent()+"");
						dispersionElement.addElement("lessThanSecondPercent").setText(specimenParam.getLessThanSecondPercent()+"");
					}else if(BasePriceRangeParam.SPECIMEN_TYPE_DISPERSION_RANGE.equals(specimenParam.getSpecimenType())){
						//离散度限制范围
						Element dispersionRangeElement = specimenRangeElement.addElement("dispersionRange");
						dispersionRangeElement.addElement("defaultScore").setText(ObjectUtils.getObjString(specimenParam.getPriceScore()));
						dispersionRangeElement.addElement("supplierNum").setText(specimenParam.getSupplierNum()+"");
						dispersionRangeElement.addElement("downFloatPercent").setText(specimenParam.getDispersionFilterMaxRange()+"");
						dispersionRangeElement.addElement("includeDownFloatPercent").setText(specimenParam.isIncludeDispersionFilterMinRange()+"");
						dispersionRangeElement.addElement("upFloatPercent").setText(specimenParam.getDispersionFilterMinRange()+"");
						dispersionRangeElement.addElement("includeUpFloatPercent").setText(specimenParam.isIncludeDispersionFilterMaxRange()+"");
						dispersionRangeElement.addElement("heightSecondFirstDeviationPercent").setText(ObjectUtils.getObjString(specimenParam.getHeightSecondFirstDeviationPercent()));
						dispersionRangeElement.addElement("includeHeightSecondFirstDeviationPercent").setText(specimenParam.isIncludeHeightSecondFirstDeviationPercent()+"");
						dispersionRangeElement.addElement("heightAvgDeviationPercent").setText(ObjectUtils.getObjString(specimenParam.getHeightAvgDeviationPercent()));
						dispersionRangeElement.addElement("includeHeightAvgDeviationPercent").setText(specimenParam.isIncludeHeightAvgDeviationPercent()+"");
						
						Element specimenFilterConditionItemListElement = dispersionRangeElement.addElement("specimenFilterConditionItemList");
						List<SpecimenFilterConditionItem> specimenFilterConditionItemList = specimenParam.getSpecimenFilterConditionItemList();
						if(null != specimenFilterConditionItemList && specimenFilterConditionItemList.size() > 0) {
							for(SpecimenFilterConditionItem item : specimenFilterConditionItemList) {
								Element itemElement = specimenFilterConditionItemListElement.addElement("specimenFilterConditionItem");
								itemElement.addElement("compareType").setText(item.getCompareType());
								itemElement.addElement("deviationPercent").setText(ObjectUtils.getObjString(item.getDeviationPercent()));
								itemElement.addElement("include").setText(item.isInclude()+"");
								itemElement.addElement("isRemoveLow").setText(item.isRemoveLow()+"");
							}
						}
					}else {
						//其他
						Element otherElement = specimenRangeElement.addElement("other");
						otherElement.addElement("defaultScore").setText(ObjectUtils.getObjString(specimenParam.getPriceScore()));
						otherElement.addElement("priceCeiling").setText(ObjectUtils.getObjString(specimenParam.getPriceCeiling()));
						otherElement.addElement("priceCeilingType").setText(ObjectUtils.getObjString(specimenParam.getCeilingType()));
						Element priceCeilingPercentElement = otherElement.addElement("priceCeilingPercent");
						priceCeilingPercentElement.addElement("supplierNum").setText(specimenParam.getSupplierNum()+"");
						priceCeilingPercentElement.addElement("priceCeilingPercent").setText(ObjectUtils.getObjString(specimenParam.getPriceCeilingPercent()));
						priceCeilingPercentElement.addElement("effectiveSupplierNum").setText(ObjectUtils.getObjString(specimenParam.getEffectiveSupplierNum()));
					}
				
				}
				
				//基准价计算
				if(null != basePriceParam) {
					Element basePriceElement = priceFormulaElement.addElement("basePrice");
					basePriceElement.addElement("basePricePoint").setText(ObjectUtils.getObjString(priceParam.getBasePricePoint()));
					basePriceElement.addElement("basePriceType").setText(ObjectUtils.getObjString(basePriceParam.getBasePriceType()));
					
					//评标价
					Element evaluationPriceElement = basePriceElement.addElement("evaluationPrice");
					evaluationPriceElement.addElement("basePriceCategory").setText(ObjectUtils.getObjString(basePriceParam.getEvaluationPriceType()));
					//算数平均法
					Element avgPriceElement = basePriceElement.addElement("avgPrice");
					avgPriceElement.addElement("floatType").setText(basePriceParam.isDownFloat() ? "02" : "");
					avgPriceElement.addElement("floatValue").setText(ObjectUtils.getObjString(basePriceParam.getBasePriceFloat()));
					avgPriceElement.addElement("useMinPriceCondition").setText(basePriceParam.isUseMinPriceCondition()+ "");
					avgPriceElement.addElement("supplierNum").setText(ObjectUtils.getObjString(basePriceParam.getSupplierNum()));
					avgPriceElement.addElement("belowFloatValue").setText(ObjectUtils.getObjString(basePriceParam.getBelowFloat()));
					avgPriceElement.addElement("priceLowSecondLowestPrice").setText(basePriceParam.isBasePriceUnderMinEvalPrice()+"");
					avgPriceElement.addElement("basePriceUnderMinPrice").setText(basePriceParam.isBasePriceUnderMinPrice()+"");
					
					//算数平均值动态浮动
					Element avgFloatRangeElement = basePriceElement.addElement("avgFloatRange");
					avgFloatRangeElement.addElement("outRangeFolat").setText(ObjectUtils.getObjString(basePriceParam.getOutRangeFolat()));
					avgFloatRangeElement.addElement("outRangeFolatDownFloat").setText(basePriceParam.isOutRangeFolatDownFloat() + "");
					Element avgFloatRangeItemListElement = avgFloatRangeElement.addElement("avgFloatRangeItemList");
					List<AvgFloatRangeItem> avgFloatRangeItemList = basePriceParam.getAvgFloatRangeItemList();
					if(null != avgFloatRangeItemList && avgFloatRangeItemList.size() > 0) {
						for(AvgFloatRangeItem item : avgFloatRangeItemList) {
							Element itemElement = avgFloatRangeItemListElement.addElement("avgFloatRangeItem");
							itemElement.addElement("floatRangeMin").setText(ObjectUtils.getObjString(item.getFloatRangeMin()));
							itemElement.addElement("includeFloatRangeMin").setText(item.isIncludeFloatRangeMin()+ "");
							itemElement.addElement("floatRangeMax").setText(ObjectUtils.getObjString(item.getFloatRangeMax()));
							itemElement.addElement("includeFloatRangeMax").setText(item.isIncludeFloatRangeMax()+ "");
							itemElement.addElement("avgFloat").setText(ObjectUtils.getObjString(item.getAvgFloat()));
							itemElement.addElement("downFloat").setText(item.isDownFloat()+ "");
						}
					}
				}
				
				//得分计算
				if(null != calculationParam) {
					Element scoreCalculationElement = priceFormulaElement.addElement("scoreCalculation");
					scoreCalculationElement.addElement("priceScorePoint").setText(ObjectUtils.getObjString(priceParam.getPriceScorePoint()));
					scoreCalculationElement.addElement("calculateType").setText(ObjectUtils.getObjString(calculationParam.getCalculationType()));
					scoreCalculationElement.addElement("minuend").setText(ObjectUtils.getObjString(calculationParam.getMinuend()));
					scoreCalculationElement.addElement("subtrahend").setText(ObjectUtils.getObjString(calculationParam.getSubtrahend()));
					scoreCalculationElement.addElement("divisor").setText(ObjectUtils.getObjString(calculationParam.getDivisor()));
					scoreCalculationElement.addElement("deviateRatePoint").setText(ObjectUtils.getObjString(calculationParam.getDeviateRatePoint()));
					Element costPerformanceElement = scoreCalculationElement.addElement("costPerformance");
					costPerformanceElement.addElement("scoreBase").setText(ObjectUtils.getObjString(calculationParam.getXjbScoreType()));
					
					String calculationType = calculationParam.getCalculationType();
					if (StringUtils.equals(CalculationParam.LINEAR_DEVIATE, calculationType)) {
						Element linearDeviateElement = scoreCalculationElement.addElement("linearDeviate");
						addDeviateRateParams(linearDeviateElement, calculationParam);
					} else if (StringUtils.equals(CalculationParam.ABSOLUTE, calculationType)) {
						Element absoluteElement = scoreCalculationElement.addElement("absolute");
						addDeviateRateParams(absoluteElement, calculationParam);
					}else if(StringUtils.equals(CalculationParam.PRICE_DEVIATEA, calculationType)){
						Element priceDeviateAElement = scoreCalculationElement.addElement("priceDeviateA");
						priceDeviateAElement.addElement("deviateRangeMin").setText(ObjectUtils.getObjString(BigDecimalUtils.div(calculationParam.getDeviateRangeMin(), new BigDecimal(10000))));
						priceDeviateAElement.addElement("deviateRangeMax").setText(ObjectUtils.getObjString(BigDecimalUtils.div(calculationParam.getDeviateRangeMax(), new BigDecimal(10000))));
						priceDeviateAElement.addElement("inDeviateRangeScore").setText(ObjectUtils.getObjString(calculationParam.getInDeviateRangeScore()));
						priceDeviateAElement.addElement("otherDeviateRangeBaseScore").setText(ObjectUtils.getObjString(calculationParam.getOtherDeviateRangeBaseScore()));
						addDeviateItemList(priceDeviateAElement,calculationParam);
					}else if(StringUtils.equals(CalculationParam.STAGE_DEVIATE, calculationType)){
						Element stageDeviateElement = scoreCalculationElement.addElement("stageDeviate");
						stageDeviateElement.addElement("absoluteType").setText(ObjectUtils.getObjString(calculationParam.getAbsoluteDeviate()));
						stageDeviateElement.addElement("defaultScore").setText(ObjectUtils.getObjString(calculationParam.getDefaultMinScore()));
					}
				}
			}
		}
	}
	
	private void addDeviateRateParams(Element linearDeviateElement, CalculationParam calculationParam) {
		linearDeviateElement.addElement("deviateRangeMin").setText(ObjectUtils.getObjString(calculationParam.getDeviateRangeMin()));
		linearDeviateElement.addElement("deviateRangeMax").setText(ObjectUtils.getObjString(calculationParam.getDeviateRangeMax()));
		linearDeviateElement.addElement("inDeviateRangeScore").setText(ObjectUtils.getObjString(calculationParam.getInDeviateRangeScore()));
		linearDeviateElement.addElement("otherDeviateRangeBaseScore").setText(ObjectUtils.getObjString(calculationParam.getOtherDeviateRangeBaseScore()));
		addDeviateItemList(linearDeviateElement, calculationParam );
	}

	private void addDeviateItemList(Element linearDeviateElement, CalculationParam calculationParam) {
		Element deviateItemListElement = linearDeviateElement.addElement("deviateItemList");
		List<DeviateRateItem> higherDeviateRateList = calculationParam.getHigherDeviateRateList();
		List<DeviateRateItem> lowerDeviateRateList = calculationParam.getLowerDeviateRateList();
		if(null != higherDeviateRateList && higherDeviateRateList.size() > 0) {
			for(DeviateRateItem item : higherDeviateRateList) {
				Element itemElement = deviateItemListElement.addElement("deviateItem");
				itemElement.addElement("isHighDeviate").setText("true");
				itemElement.addElement("deviateRateStart").setText(ObjectUtils.getObjString(item.getDeviateRateStart()));
				itemElement.addElement("deviatePercentUnit").setText(ObjectUtils.getObjString(item.getDeviatePercentUnit()));
				itemElement.addElement("addOrReduceType").setText(item.isReduceScore() ? "02" : "");
				itemElement.addElement("deviatePercentValue").setText(ObjectUtils.getObjString(item.getDeviatePercentValue()));
				itemElement.addElement("defaultScore").setText(ObjectUtils.getObjString(item.getDefaultScore()));
			}
		}
		if(null != lowerDeviateRateList && lowerDeviateRateList.size() > 0) {
			for(DeviateRateItem item : lowerDeviateRateList) {
				Element itemElement = deviateItemListElement.addElement("deviateItem");
				itemElement.addElement("isHighDeviate").setText("false");
				itemElement.addElement("deviateRateStart").setText(ObjectUtils.getObjString(item.getDeviateRateStart()));
				itemElement.addElement("deviatePercentUnit").setText(ObjectUtils.getObjString(item.getDeviatePercentUnit()));
				itemElement.addElement("addOrReduceType").setText(item.isReduceScore() ? "02" : "");
				itemElement.addElement("deviatePercentValue").setText(ObjectUtils.getObjString(item.getDeviatePercentValue()));
				itemElement.addElement("defaultScore").setText(ObjectUtils.getObjString(item.getDefaultScore()));
			}
		}
	}

	private void callBackMsg(String msg){
		if(null != callBack){
			callBack.callBackString(msg);
		}
	}

	/**
	 * 开始线程
	 */
	public void start() {
		thread = new Thread(this);
		thread.setName("导入指标线程");
		thread.start();
	}
	
	/**
	 * 结束线程
	 */
	public void stop() {
		thread = null;
	}
	
}
