package com.sunxung.factoring.component.util;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:TODO这里用一句话描述这个类的作用
 * @Author:wanxiangZhou
 * @E_mail:303526821@qq.com
 * @Date:2017年5月4日 下午4:54:54
 */
public abstract class Operator {

    /**
     * 运算符
     */
    private char operator;
    /**
     * 运算符的优先级别，数字越大，优先级别越高
     */
    private int priority;
    private static Map<Character, Operator> operators = new HashMap<Character, Operator>();

    private Operator(char operator, int priority){
        setOperator(operator);
        setPriority(priority);
        register(this);
    }

    private void register(Operator operator) {
        operators.put(operator.getOperator(), operator);
    }

    /**
     * 加法运算
     */
    public final static Operator ADITION = new Operator('+', 100) {

        public BigDecimal eval(BigDecimal left, BigDecimal right) {
            return left.add(right);
        }
    };
    /**
     * 减法运算
     */
    public final static Operator SUBTRATION = new Operator('-', 100) {

        public BigDecimal eval(BigDecimal left, BigDecimal right) {
            return left.subtract(right);
        }
    };
    /**
     * 乘法运算
     */
    public final static Operator MULTIPLICATION = new Operator('*', 200) {

        public BigDecimal eval(BigDecimal left, BigDecimal right) {
            return left.multiply(right);
        }
    };
    /**
     * 除法运算
     */
    public final static Operator DIVITION = new Operator('/', 200) {

        public BigDecimal eval(BigDecimal left, BigDecimal right) {
            if(right.compareTo(BigDecimal.ZERO)!=0){
                return  left.divide(right,2, BigDecimal.ROUND_HALF_EVEN);
            }
            return null;
        }
    };
    /**
     * 冪运算
     */
    public final static Operator EXPONENT = new Operator('^', 300) {

        public BigDecimal eval(BigDecimal left, BigDecimal right) {
            return left.pow(right.intValue());
        }
    };

    public char getOperator() {
        return operator;
    }

    private void setOperator(char operator) {
        this.operator = operator;
    }

    public int getPriority() {
        return priority;
    }

    private void setPriority(int priority) {
        this.priority = priority;
    }

    /**
     * 根据某个运算符获得该运算符的优先级别
     * 
     * @param c
     * @return 运算符的优先级别
     */
    public static int getPrority(char c) {
        Operator op = operators.get(c);
        return op != null ? op.getPriority() : 0;
    }

    /**
     * 工具方法，判断某个字符是否是运算符
     * 
     * @param c
     * @return 是运算符返回 true，否则返回 false
     */
    public static boolean isOperator(char c) {
        return getInstance(c) != null;
    }

    public static boolean isOperator(String str) {
        return str.length() > 1 ? false : isOperator(str.charAt(0));
    }

    /**
     * 根据运算符获得 Operator 实例
     * 
     * @param c
     * @return 从注册中的 Operator 返回实例，尚未注册返回 null
     */
    public static Operator getInstance(char c) {
        return operators.get(c);
    }

    public static Operator getInstance(String str) {
        return str.length() > 1 ? null : getInstance(str.charAt(0));
    }

    /**
     * 根据操作数进行计算
     * 
     * @param left 左操作数
     * @param right 右操作数
     * @return 计算结果
     */
    public abstract BigDecimal eval(BigDecimal left, BigDecimal right);
}
