package model;

import model.ParserException.Type;
import model.util.ColorCombinations;

/**
 * An Expression represents a mathematical expression as a tree.
 * 
 * In this format, the internal nodes represent mathematical 
 * functions and the leaves represent constant values.
 *
 * @author former student solution
 * @author Robert C. Duvall (added comments, some code)
 */
public class Expression
{
    private RGBColor myValue;
    private String myCommand;
    private Expression myOperand1;
    private Expression myOperand2;


    /**
     * Create expression representing the given constant value
     */
    public Expression (RGBColor value)
    {
        myValue = value;
        myCommand = null;
        myOperand1 = null;
        myOperand2 = null;
    }


    /**
     * Create expression representing the given operation between the
     * two given sub-expressions.
     */
    public Expression (String command, Expression operand1, Expression operand2)
    {
        myCommand = command;
        myOperand1 = operand1;
        myOperand2 = operand2;
        myValue = null;
    }


    /**
     * @return value of expression
     */
    public RGBColor evaluate ()
    {
        if (myCommand == null)
        {
            return myValue;
        }
        else
        {
            if (myCommand.equals("plus"))
                return ColorCombinations.add(myOperand1.evaluate(), myOperand2.evaluate());
            else if (myCommand.equals("minus"))
                return ColorCombinations.subtract(myOperand1.evaluate(), myOperand2.evaluate());
            else if (myCommand.equals("mul"))
                return ColorCombinations.multiply(myOperand1.evaluate(), myOperand2.evaluate());
            else if (myCommand.equals("div"))
                return ColorCombinations.divide(myOperand1.evaluate(), myOperand2.evaluate());
            else
                throw new ParserException("Unknown Command " + myCommand, Type.UNKNOWN_COMMAND);
        }
    }


    /**
     * @return string representation of expression
     */
    public String toString ()
    {
        StringBuffer result = new StringBuffer();
        if (myCommand == null)
        {
            result.append(myValue); 
        }
        else
        {
            result.append("(");
            result.append(" " + myCommand + " ");
            result.append(myOperand1.toString());  
            result.append(myOperand2.toString());
            result.append(")");
        }
        return result.toString();
    }
}
