using Rubberduck.Parsing.Abstract;

namespace Rubberduck.Parsing.Expressions;

public sealed class UnaryMinusExpression : Expression
{
    private readonly IExpression _expression;

    public UnaryMinusExpression(IExpression expression)
    {
        _expression = expression;
    }

    public override IValue Evaluate()
    {
        var operand = _expression.Evaluate();
        if (operand == null)
        {
            return null;
        }
        else if (operand.ValueType == ValueType.Date)
        {
            var value = operand.AsDecimal;
            value = -value;
            try
            {
                return new DateValue(new DecimalValue(value).AsDate);
            }
            catch
            {
                // 5.6.9.3.1: If overflow occurs during the coercion to Date, and the operand has a 
                // declared type of Variant, the result is the Double value.
                // We don't care about it being a Variant because if it's not a Variant it won't compile/run.
                // We catch everything because the only case where the code is valid is that if this is an overflow.
                return new DecimalValue(value);
            }
        }
        else
        {
            var value = operand.AsDecimal;
            return new DecimalValue(-value);
        }
    }
}
