from ..token import Token
from .node import Node
from .constant import Constant
from .identifier import Identifier
from .expression import Expression


class Operand(Node):
    """
    An operand.
    """

    def __init__(self):
        """
        Create the operand.
        """

        self.value = None

    @classmethod
    def parse(cls, tokenizer, identifiers):
        """
        Parse an operand.
        """

        operand = Operand()
        if tokenizer.get_token() == Token.INTEGER_CONSTANT:
            operand.value = Constant.parse(tokenizer, identifiers)

        elif tokenizer.get_token() == Token.IDENTIFIER:
            operand.value = Identifier.parse(tokenizer, identifiers)

        else:
            cls.extract_token(tokenizer, Token.OPENING_PARENTHESIS)
            operand.value = Expression.parse(tokenizer, identifiers)
            cls.extract_token(tokenizer, Token.CLOSING_PARENTHESIS)

        return operand

    def evaluate(self, identifiers):
        """
        Evaluate the operand and return its value.
        """

        if isinstance(self.value, Expression):
            return self.value.evaluate(identifiers)

        elif isinstance(self.value, Identifier):
            return identifiers.get_value(self.value.name)

        else:
            return self.value.value

    def __str__(self):
        """
        Human-readable string representation.
        """

        parts = [self.value]
        if isinstance(self.value, Expression):
            parts = [
                Token.OPENING_PARENTHESIS.value[1],
                self.value,
                Token.CLOSING_PARENTHESIS.value[1]]

        return " ".join(map(lambda d: str(d), parts))
