package utils;

import java.util.Map;

import exceptions.NonLinearExpressionException;
import models.algebra.Constant;
import models.algebra.Expression;
import models.algebra.Symbol;
import models.algebra.Term;
import models.algebra.Variable;
import models.dataConstraintModel.DataConstraintModel;

public class ExpressionUitls {

	
	public static int getCoefficientAndConstantsFromExpression(Expression expression, Map<Variable, Integer> coefficients, int curWeight) {
		int res = 0;
		if(expression instanceof Constant) {
			return getConstantValue((Constant) expression) * curWeight;
		} else if(expression instanceof Variable) {
			coefficients.put((Variable) expression, coefficients.getOrDefault((Variable) expression, 0) + curWeight);
			return 0;
		}
		Term term = (Term) expression;
		Symbol symbol = term.getSymbol();
		if(symbol.equals(DataConstraintModel.add)) {
			Expression c1 = term.getChild(0);
			Expression c2 = term.getChild(1);
			res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight);
			res += getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight);
		} else if(symbol.equals(DataConstraintModel.sub)) {
			Expression c1 = term.getChild(0);
			Expression c2 = term.getChild(1);
			res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight);
			res += getCoefficientAndConstantsFromExpression(c2, coefficients, -curWeight);
		} else if(symbol.equals(DataConstraintModel.mul)) {
			Expression c1 = term.getChild(0);
			Expression c2 = term.getChild(1);
			if(c1.getVariables().size() == 0 && c2.getVariables().size() == 0) {
				res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight) * 
						getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight);
			} else if(c1.getVariables().size() == 0) {
				res += getCoefficientAndConstantsFromExpression(
							c2, 
							coefficients, 
							getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight)
						);
			} else if(c2.getVariables().size() == 0){
				res += getCoefficientAndConstantsFromExpression(
						c1, 
						coefficients, 
						getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight)
					);
			} else {
				throw new NonLinearExpressionException("Order expression must be linear expression.");
			}
		} else if(symbol.equals(DataConstraintModel.minus)) {
			Expression c1 = term.getChild(0);
			res += getCoefficientAndConstantsFromExpression(c1, coefficients, -curWeight);
		} else {
			throw new NonLinearExpressionException("Order expression must be linear expression.");
		}
		return res;
		
	}
	
	public static int getConstantValue(Constant constant) {
		return Integer.parseInt((String) constant.getValue());
	}
	
}
