package nccloud.web.hrwa.waruleex.action.formula;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import nc.hr.utils.ResHelper;
import nc.ui.pub.formulaparse.FormulaParse;
import nc.vo.pub.BusinessException;
import nc.vo.pub.formulaset.FormulaParseFather;
import nc.vo.wa.pub.WaLoginContext;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.json.JsonFactory;
import nccloud.web.hr.pub.HRCommonAction;
import nccloud.web.hr.pub.HRNccFormulaHelper;
import nccloud.web.hrwa.helper.WaLoginContextUtils;
import nccloud.web.hrwa.waruleex.action.formula.pub.TranslateFormula;
import nccloud.web.uapbd.commons.web.ParamUtils;

/**
 * 薪资发放项目 验证和确认公式,如果公式没有转换，则增加转换功能
 * 
 * @author YuCheng
 *
 */
public class WaRuleExFormulaValidateAction extends HRCommonAction {

	@Override
	public <T> Object execute(IRequest request, T para) throws BusinessException {
		ParamUtils param = new ParamUtils(request);
		WaLoginContext context = WaLoginContextUtils.getWaLoginContext(param);
		String formulaStr = param.getString("formulastr", null);// 文本公式

		// 需要传递的额外条件，暂时只有籍贯的参照在使用
		String condition = param.getString("condition", null);
		String formula = param.getString("formula", null);
		// 处理行政区域参照
		String dynPara= param.getString("dynPara", "");
		if (formulaStr != null) {
			if (StringUtils.isBlank(formula)) {
				// 将文本公式进行转换
				dynPara = StringUtils.isBlank(dynPara) ? new HRNccFormulaHelper().getCountryPk(formula,formulaStr) : dynPara;
				formula = new TranslateFormula().translateFormula(context, formulaStr, condition, dynPara);
			}

			formula = resetNameOfWaGrade(formulaStr, formula);
			// 对公示进行校验
			String[] formulas = splitFormulaText(formula);
			FormulaParseFather f = new FormulaParse("hrwa");
			if (!f.checkExpressArray(formulas)) {
				throw new BusinessException(ResHelper.getString("formulaparse",
						"UPPformulaparse-000057")/* @res "公式验证失败!" */);
			}
		} else {
			formula = null;
		}
		Map<String, String> resultMap = new HashMap<String, String>();
		resultMap.put("formula", formula);
		resultMap.put("formulaStr", formulaStr);
		return JsonFactory.create().toJson(resultMap);
	}
	
	private String[] splitFormulaText(String formulaText) {
		formulaText = formulaText.replaceAll("\n", "").replaceAll("\t", "").replaceAll(" ", "");
		return formulaText.split(";");
	}
	/**
	 * 20140608 shenliangc 解决薪资规则公式引用薪资标准表时编辑显示脚本语言而不显示业务语言的问题。
	 * @param formula
	 * @return String
	 */
	public String resetNameOfWaGrade(String formulaStr,String formula) throws BusinessException {
		formula= (!formula.contains(".") && formulaStr.contains(".")) ? formulaStr : formula;
		try {
			if (StringUtils.isEmpty(formula)) {
				return "";
			}
			// 目前的逻辑只处理了简单公式的情况，复杂公式需要将公式先截断成多个简单公式进行处理。
			// 由于薪资规则公式只允许使用“或者”“并且”联接简单公式，因此以此为标记截断公式。
			// 然后对所有得到的简单公式进行处理，最后将公式重新联接起来返回。
			// 处理过程包含较多的字符串操作，在复杂度方面有点问题。
			ArrayList<String> subFormulaList = new ArrayList<String>();
			while (formula.contains("或者") || formula.contains("并且")) {
				int splitPosition = getSplitPosition(formula);
				subFormulaList.add(formula.substring(splitPosition));
				formula = formula.substring(0, splitPosition);
			}
			subFormulaList.add(formula);
			// 复杂公式拆分成多个简单公式完成，每个简单公式都只包含一个"="
			// 每个简单公式分别处理薪资标准表名称
			String[] subFormulaArray = subFormulaList.toArray(new String[0]);
			for (int i = subFormulaArray.length; i > 0; i--) {
				String subFormula = subFormulaArray[i - 1];
				// 此时公式的形式如下：
				// [薪资标准设置.集团总部岗位工资薪点标准表<级别>] = "1001PP1000000000H2FZ"
				// 首先区分等号右边的主键是薪资标准表中的档别还是级别主键
				String fieldCode = "";
				if (subFormula.indexOf("<") > 0 && subFormula.indexOf(">") > 0) {
					fieldCode = subFormula.substring(subFormula.indexOf("<") + 1, subFormula.indexOf(">"));
				}
				String condition = "";
				if (subFormula.indexOf("=") > 0) {
					condition = subFormula.substring(subFormula.indexOf("=") + 1).replace("\"", "").trim();
				}
				String nameOfWaCriterion = "";
				String oldName = "";
				if (subFormula.contains(".") && subFormula.contains("<")) {
					oldName = subFormula.substring(subFormula.indexOf(".") + 1, subFormula.indexOf("<"));
				}
				if (!StringUtils.isEmpty(oldName) && !StringUtils.isEmpty(nameOfWaCriterion)
						&& !oldName.equals(nameOfWaCriterion)) {
					subFormula = subFormula.replace(oldName, nameOfWaCriterion);
					subFormulaArray[i - 1] = subFormula;
				}
			}
		} catch (Exception e) {
			throw new BusinessException(ResHelper.getString("formulaparse",
					"UPPformulaparse-000057")/* @res "公式验证失败!" */);
		}
		return formula;
	}
	/**
	 * 20140608 shenliangc 解决薪资规则公式引用薪资标准表时编辑显示脚本语言而不显示业务语言的问题。
	 * 查找公式中最后一个“并且”或“或者”的位置
	 * @param formula
	 * @return int
	 */
	private int getSplitPosition(String formula)
	{
	    int lastIndexOfAnd = formula.lastIndexOf("并且");
	    int lastIndexOfOr = formula.lastIndexOf("或者");
	    
	    return lastIndexOfAnd > lastIndexOfOr ? lastIndexOfAnd : lastIndexOfOr;
	}

}
