// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// A token that composes an expression. There are several kinds of tokens
/// that represent arithmetic operation symbols, numbers and pieces of numbers.
/// We need to represent pieces of numbers because the user may have only
/// entered a partial expression so far.
class ExpressionToken {
  ExpressionToken(this.stringRep);

  final String? stringRep;

  @override
  String toString() => stringRep!;
}

/// A token that represents a number.
class NumberToken extends ExpressionToken {
  NumberToken(String super.stringRep, this.number);

  NumberToken.fromNumber(num number) : this('$number', number);

  final num number;
}

/// A token that represents an integer.
class IntToken extends NumberToken {
  IntToken(String stringRep) : super(stringRep, int.parse(stringRep));
}

/// A token that represents a floating point number.
class FloatToken extends NumberToken {
  FloatToken(String stringRep) : super(stringRep, _parse(stringRep));

  static double _parse(String stringRep) {
    String toParse = stringRep;
    if (toParse.startsWith('.'))
      toParse = '0$toParse';
    if (toParse.endsWith('.'))
      toParse = '${toParse}0';
    return double.parse(toParse);
  }
}

/// A token that represents a number that is the result of a computation.
class ResultToken extends NumberToken {
  ResultToken(num number) : super.fromNumber(round(number));

  /// rounds `number` to 14 digits of precision. A double precision
  /// floating point number is guaranteed to have at least this many
  /// decimal digits of precision.
  static num round(num number) {
    if (number is int)
      return number;
    return double.parse(number.toStringAsPrecision(14));
  }
}

/// A token that represents the unary minus prefix.
class LeadingNegToken extends ExpressionToken {
  LeadingNegToken() : super('-');
}

enum Operation { Addition, Subtraction, Multiplication, Division }

/// A token that represents an arithmetic operation symbol.
class OperationToken extends ExpressionToken {
  OperationToken(this.operation)
   : super(opString(operation));

  Operation operation;

  static String? opString(Operation operation) {
    switch (operation) {
      case Operation.Addition:
        return ' + ';
      case Operation.Subtraction:
        return ' - ';
      case Operation.Multiplication:
        return '  \u00D7  ';
      case Operation.Division:
        return '  \u00F7  ';
    }
  }
}

/// As the user taps different keys the current expression can be in one
/// of several states.
enum ExpressionState {
  /// The expression is empty or an operation symbol was just entered.
  /// A new number must be started now.
  Start,

  /// A minus sign was entered as a leading negative prefix.
  LeadingNeg,

  /// We are in the midst of a number without a point.
  Number,

  /// A point was just entered.
  Point,

  /// We are in the midst of a number with a point.
  NumberWithPoint,

  /// A result is being displayed
  Result,
}

/// An expression that can be displayed in a calculator. It is the result
/// of a sequence of user entries. It is represented by a sequence of tokens.
///
/// The tokens are not in one to one correspondence with the key taps because we
/// use one token per number, not one token per digit. A [CalcExpression] is
/// immutable. The `append*` methods return a new [CalcExpression] that
/// represents the appropriate expression when one additional key tap occurs.
class CalcExpression {
  CalcExpression(this._list, this.state);

  CalcExpression.empty()
    : this(<ExpressionToken>[], ExpressionState.Start);

  CalcExpression.result(FloatToken result)
    : _list = <ExpressionToken?>[],
      state = ExpressionState.Result {
    _list.add(result);
  }

  /// The tokens comprising the expression.
  final List<ExpressionToken?> _list;
  /// The state of the expression.
  final ExpressionState state;

  /// The string representation of the expression. This will be displayed
  /// in the calculator's display panel.
  @override
  String toString() {
    final StringBuffer buffer = StringBuffer();
    buffer.writeAll(_list);
    return buffer.toString();
  }

  /// Append a digit to the current expression and return a new expression
  /// representing the result. Returns null to indicate that it is not legal
  /// to append a digit in the current state.
  CalcExpression? appendDigit(int digit) {
    ExpressionState newState = ExpressionState.Number;
    ExpressionToken? newToken;
    final List<ExpressionToken?> outList = _list.toList();
    switch (state) {
      case ExpressionState.Start:
        // Start a new number with digit.
        newToken = IntToken('$digit');
        break;
      case ExpressionState.LeadingNeg:
        // Replace the leading neg with a negative number starting with digit.
        outList.removeLast();
        newToken = IntToken('-$digit');
        break;
      case ExpressionState.Number:
        final ExpressionToken last = outList.removeLast()!;
        newToken = IntToken('${last.stringRep}$digit');
        break;
      case ExpressionState.Point:
      case ExpressionState.NumberWithPoint:
        final ExpressionToken last = outList.removeLast()!;
        newState = ExpressionState.NumberWithPoint;
        newToken = FloatToken('${last.stringRep}$digit');
        break;
      case ExpressionState.Result:
        // Cannot enter a number now
        return null;
    }
    outList.add(newToken);
    return CalcExpression(outList, newState);
  }

  /// Append a point to the current expression and return a new expression
  /// representing the result. Returns null to indicate that it is not legal
  /// to append a point in the current state.
  CalcExpression? appendPoint() {
    ExpressionToken? newToken;
    final List<ExpressionToken?> outList = _list.toList();
    switch (state) {
      case ExpressionState.Start:
        newToken = FloatToken('.');
        break;
      case ExpressionState.LeadingNeg:
      case ExpressionState.Number:
        final ExpressionToken last = outList.removeLast()!;
        final String value = last.stringRep!;
        newToken = FloatToken('$value.');
        break;
      case ExpressionState.Point:
      case ExpressionState.NumberWithPoint:
      case ExpressionState.Result:
        // Cannot enter a point now
        return null;
    }
    outList.add(newToken);
    return CalcExpression(outList, ExpressionState.Point);
  }

  /// Append an operation symbol to the current expression and return a new
  /// expression representing the result. Returns null to indicate that it is not
  /// legal to append an operation symbol in the current state.
  CalcExpression? appendOperation(Operation op) {
    switch (state) {
      case ExpressionState.Start:
      case ExpressionState.LeadingNeg:
      case ExpressionState.Point:
        // Cannot enter operation now.
        return null;
      case ExpressionState.Number:
      case ExpressionState.NumberWithPoint:
      case ExpressionState.Result:
        break;
    }
    final List<ExpressionToken?> outList = _list.toList();
    outList.add(OperationToken(op));
    return CalcExpression(outList, ExpressionState.Start);
  }

  /// Append a leading minus sign to the current expression and return a new
  /// expression representing the result. Returns null to indicate that it is not
  /// legal to append a leading minus sign in the current state.
  CalcExpression? appendLeadingNeg() {
    switch (state) {
      case ExpressionState.Start:
        break;
      case ExpressionState.LeadingNeg:
      case ExpressionState.Point:
      case ExpressionState.Number:
      case ExpressionState.NumberWithPoint:
      case ExpressionState.Result:
        // Cannot enter leading neg now.
        return null;
    }
    final List<ExpressionToken?> outList = _list.toList();
    outList.add(LeadingNegToken());
    return CalcExpression(outList, ExpressionState.LeadingNeg);
  }

  /// Append a minus sign to the current expression and return a new expression
  /// representing the result. Returns null to indicate that it is not legal
  /// to append a minus sign in the current state. Depending on the current
  /// state the minus sign will be interpreted as either a leading negative
  /// sign or a subtraction operation.
  CalcExpression? appendMinus() {
    switch (state) {
      case ExpressionState.Start:
        return appendLeadingNeg();
      case ExpressionState.LeadingNeg:
      case ExpressionState.Point:
      case ExpressionState.Number:
      case ExpressionState.NumberWithPoint:
      case ExpressionState.Result:
        return appendOperation(Operation.Subtraction);
    }
  }

  /// Computes the result of the current expression and returns a new
  /// ResultExpression containing the result. Returns null to indicate that
  /// it is not legal to compute a result in the current state.
  CalcExpression? computeResult() {
    switch (state) {
      case ExpressionState.Start:
      case ExpressionState.LeadingNeg:
      case ExpressionState.Point:
      case ExpressionState.Result:
        // Cannot compute result now.
        return null;
      case ExpressionState.Number:
      case ExpressionState.NumberWithPoint:
        break;
    }

    // We make a copy of _list because CalcExpressions are supposed to
    // be immutable.
    final List<ExpressionToken?> list = _list.toList();
    // We obey order-of-operations by computing the sum of the 'terms',
    // where a "term" is defined to be a sequence of numbers separated by
    // multiplication or division symbols.
    num currentTermValue = removeNextTerm(list);
    while (list.isNotEmpty) {
      final OperationToken opToken = list.removeAt(0)! as OperationToken;
      final num nextTermValue = removeNextTerm(list);
      switch (opToken.operation) {
        case Operation.Addition:
          currentTermValue += nextTermValue;
          break;
        case Operation.Subtraction:
          currentTermValue -= nextTermValue;
          break;
        case Operation.Multiplication:
        case Operation.Division:
          // Logic error.
          assert(false);
      }
    }
    final List<ExpressionToken> outList = <ExpressionToken>[
      ResultToken(currentTermValue),
    ];
    return CalcExpression(outList, ExpressionState.Result);
  }

  /// Removes the next "term" from `list` and returns its numeric value.
  /// A "term" is a sequence of number tokens separated by multiplication
  /// and division symbols.
  static num removeNextTerm(List<ExpressionToken?> list) {
    assert(list.isNotEmpty);
    final NumberToken firstNumToken = list.removeAt(0)! as NumberToken;
    num currentValue = firstNumToken.number;
    while (list.isNotEmpty) {
      bool isDivision = false;
      final OperationToken nextOpToken = list.first! as OperationToken;
      switch (nextOpToken.operation) {
        case Operation.Addition:
        case Operation.Subtraction:
          // We have reached the end of the current term
          return currentValue;
        case Operation.Multiplication:
          break;
        case Operation.Division:
          isDivision = true;
      }
      // Remove the operation token.
      list.removeAt(0);
      // Remove the next number token.
      final NumberToken nextNumToken = list.removeAt(0)! as NumberToken;
      final num nextNumber = nextNumToken.number;
      if (isDivision)
        currentValue /= nextNumber;
      else
        currentValue *= nextNumber;
    }
    return currentValue;
  }
}
