package com.steering.pss.plnsaleord.base;

import java.util.ArrayList;
import java.util.LinkedList;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
 * 通用方法
 * @author xiaohai
 */
public class CorePlnComm {

    /**
     * 字符串解析计算公式返回计算结果（加、减、乘、除）
     * @param formula 计算式
     * @return Object
     */
    public static Object countFormula(String formula) throws ScriptException {
        ScriptEngine jse = new ScriptEngineManager()
                .getEngineByName("JavaScript");
        return jse.eval(formula);
    }

    /**
     * 字符串右对齐
     * @param str 要左填充的字符串
     * @param charc 要填充的字符
     * @param len 填充后的长度
     * @return 填充后的字符串
     */
    public static String padding(String str, char charc, int len) {
        StringBuffer sbf = new StringBuffer("");

        for (int i = 0; i < (len - str.length()); i++) {
            sbf.append(charc);
        }
        return sbf.toString() + str;
    }
    /**
     * 字符串解析计算公式返回计算结果（加、减、乘、除）
     * @param formula 计算式
     * @return Object
     */
    private static boolean isRightFormat = true;

    public static double getResult(String formula) {
        double returnValue = 0;
        try {
            returnValue = doAnalysis(formula);
        }
        catch (NumberFormatException nfe) {
            System.out.println("公式格式有误，请检查:" + formula);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        if (!isRightFormat) {
            System.out.println("公式格式有误，请检查:" + formula);
        }
        return returnValue;
    }

    private static double doAnalysis(String formula) {
        double returnValue = 0;
        LinkedList<Integer> stack = new LinkedList<Integer>();
        int curPos = 0;
        String beforePart = "";
        String afterPart = "";
        String calculator = "";
        isRightFormat = true;
        while (isRightFormat
                && (formula.indexOf('(') >= 0 || formula.indexOf(')') >= 0)) {
            curPos = 0;
            for (char s : formula.toCharArray()) {
                if (s == '(') {
                    stack.add(curPos);
                }
                else if (s == ')') {
                    if (stack.size() > 0) {
                        beforePart = formula.substring(0, stack.getLast());
                        afterPart = formula.substring(curPos + 1);
                        calculator = formula.substring(stack.getLast() + 1,
                                curPos);
                        formula = beforePart + doCalculation(calculator)
                                + afterPart;
                        stack.clear();
                        break;
                    }
                    else {
                        System.out.println("有未关闭的右括号！");
                        isRightFormat = false;
                    }
                }
                curPos++;
            }
            if (stack.size() > 0) {
                System.out.println("有未关闭的左括号！");
                break;
            }
        }
        if (isRightFormat) {
            returnValue = doCalculation(formula);
        }
        return returnValue;
    }

    private static double doCalculation(String formula) {
        ArrayList<Double> values = new ArrayList<Double>();
        ArrayList<String> operators = new ArrayList<String>();
        int curPos = 0;
        int prePos = 0;
        int minus = 0;
        if(formula.contains("%")){ 
            formula=formula.replaceAll("%", "/100*");
        }
        for (char s : formula.toCharArray()) {
            if ((s == '+' || s == '-' || s == '*' || s == '/') && minus != 0
                    && minus != 2) {
                values.add(Double.parseDouble(formula.substring(prePos, curPos)
                        .trim()));
                operators.add("" + s);
                prePos = curPos + 1;
                minus = minus + 1;
            }
            else {
                minus = 1;
            }
            curPos++;
        }
        values.add(Double.parseDouble(formula.substring(prePos).trim()));
        char op;
//        for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
//            op = operators.get(curPos).charAt(0);
//            switch (op) {
//            case '%':
//                values.add(curPos, values.get(curPos+1) /100);
//                values.remove(curPos + 1);
//                values.remove(curPos + 1);
//                operators.remove(curPos);
//                curPos = -1;
//                break; 
//            }
//        }
        for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
            op = operators.get(curPos).charAt(0);
            switch (op) {
            case '*':
                values.add(curPos, values.get(curPos) * values.get(curPos + 1));
                values.remove(curPos + 1);
                values.remove(curPos + 1);
                operators.remove(curPos);
                curPos = -1;
                break;
            case '/':
                values.add(curPos, values.get(curPos) / values.get(curPos + 1));
                values.remove(curPos + 1);
                values.remove(curPos + 1);
                operators.remove(curPos);
                curPos = -1;
                break;
            }
        }
        for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
            op = operators.get(curPos).charAt(0);
            switch (op) {
            case '+':
                values.add(curPos, values.get(curPos) + values.get(curPos + 1));
                values.remove(curPos + 1);
                values.remove(curPos + 1);
                operators.remove(curPos);
                curPos = -1;
                break;
            case '-':
                values.add(curPos, values.get(curPos) - values.get(curPos + 1));
                values.remove(curPos + 1);
                values.remove(curPos + 1);
                operators.remove(curPos);
                curPos = -1;
                break;
            }
        }
        
        return values.get(0).doubleValue();
    }
}