import 'package:aman_kassa_flutter/core/models/calc_model.dart';

class Calculations {
  static const PERIOD = '.';
  static const MULTIPLY = '*';
  static const SUBTRACT = '-';
  static const ADD = '+';
  static const NONE = 'none';

  static const ERASE = '<<';
  static const CLEAR = 'C';
  static const EQUAL = '=';
  static const OPERATIONS = [
    Calculations.ADD,
    Calculations.MULTIPLY,
    Calculations.SUBTRACT,
    Calculations.ERASE
  ];

  static double add(double a, double b) => a + b;

  static double subtract(double a, double b) => a - b;

  static double divide(double a, double b) => a / b;

  static double multiply(double a, double b) => a * b;
}

class Calculator {
  static String parseItems(List<CalcModel> items, bool isEqual) {
    if (isEqual) {
      return _viewResult(items);
    } else {
      return _viewValues(items);
    }
  }

  static String _viewResult(List<CalcModel> items) {
    String str = '';
    if (items.isNotEmpty) {
      CalcModel last = items.removeLast();
      if (last.operation == Calculations.NONE && last.num1 != '0') {
        last.operation = Calculations.ADD;
      } else if (last.operation == Calculations.MULTIPLY) {
        if (last.num2 == null) {
          last.num2 = '1';
          last.operation = Calculations.ADD;
        }
      }
      last.closed = true;
      items.add(last);
      double summ = 0.0;
      for (var i = 0; i < items.length; i++) {
        var row = items[i];
        if (row.operation == Calculations.MULTIPLY) {
          str += "${row.num1} * ${row.num2}" ;
          summ += double.parse(row.num1) * double.parse(row.num2!);
        } else {
          str += row.num1;
          summ += double.parse(row.num1) ;
        }

        if (row.closed) {
          if (i < items.length - 1) {
            str += " + ";
          } else {
            str += " = ";
          }
        }
      }

      str += summ.toStringAsFixed(2);

    }
    return str;
  }

  static String _viewValues(List<CalcModel> items) {
    String str = '';
    for (var i = 0; i < items.length; i++) {
      CalcModel row = items[i];
      if (row.operation == Calculations.ADD) {
        str += row.num1;
      } else if (row.operation == Calculations.MULTIPLY) {
        if (row.num2 == null) {
          str += row.num1 + " * ";
        } else {
          str += row.num1 + " * " + row.num2!;
        }
      } else if (row.operation == Calculations.NONE) {
        str += row.num1;
      } else if (row.operation == Calculations.EQUAL) {
        str += row.num1;
      }
      if (row.closed) {
        str += " + ";
      }
    }
    return str;
  }

  static List<CalcModel> action({required String value, required List<CalcModel> items}) {
    switch (value) {
      case Calculations.ADD:
        {
          items = _setPlus(value: value, items: items);
        }
        break;
      case Calculations.MULTIPLY:
        {
          items = _setMultiply(value: value, items: items);
        }
        break;
      case Calculations.ERASE:
        {
          items = _setBackward(value: value, items: items);
        }
        break;
      case Calculations.CLEAR:
        {
          items = _setClean(value: value, items: items);
        }
        break;
      case Calculations.PERIOD:
        {
          items = _setDot(value: value, items: items);
        }
        break;
      case Calculations.EQUAL:
        {
          items = _setEqual(value: value, items: items);
        }
        break;

      default:
        {
          items = _setNumber(value: value, items: items);
        }
        break;
    }

    return [...items];
  }

  static List<CalcModel> _setNumber({required String value, required List<CalcModel> items}) {
    if (items.isEmpty) {
      items.add(CalcModel(num1: value, operation: Calculations.NONE));
    } else {
      CalcModel last = items.removeLast();
      if (last.closed) {
        items.add(last);
        items.add(CalcModel(num1: value, operation: Calculations.NONE));
      } else {
        if (value == '0' && last.num1 == '0') {
          last.operation = Calculations.NONE;
          items.add(last);
        } else if (value == '0' && last.num1 == '0.') {
          last.num1 += value;
          last.operation = Calculations.NONE;
          items.add(last);
        } else {
          if (last.operation == Calculations.NONE) {
            if (last.num1 == '0' && value != '0') {
              last.num1 = value;
            } else {
              last.num1 += value;
            }
            items.add(last);
          } else if (last.operation == Calculations.MULTIPLY) {
            if(last.num2 == null)
              last.num2 = value;
            else if(last.num2 !=null) {
              last.num2 = last.num2! + value;
            }
            last.operation = Calculations.MULTIPLY;
            items.add(last);
          } else if (last.operation == Calculations.ADD) {
            last.operation = Calculations.ADD;
            items.add(last);
          }
        }
      }
    }
    return [...items];
  }

  static List<CalcModel> _setPlus({required String value, required List<CalcModel> items}) {
    if (items.isNotEmpty) {
      CalcModel last = items.removeLast();
      if (last.closed) {
        items.add(last);
      } else {
        if (last.operation == Calculations.NONE) {
          if (last.num1 != '0') {
            last.num2 = '1';
            last.operation = Calculations.ADD;
            last.closed = true;
          }
          items.add(last);
        } else if (last.operation == Calculations.MULTIPLY) {
          if (last.num2 == null) {
            last.num2 = '1';
            last.operation = Calculations.ADD;
          }
          last.closed = true;
          items.add(last);
        } else {
          last.closed = true;
          items.add(last);
        }
      }
    }
    return [...items];
  }

  static List<CalcModel> _setDot({required String value, required List<CalcModel> items}) {
    if (items.isNotEmpty) {
      CalcModel last = items.removeLast();
      if (last.operation == Calculations.NONE) {
        if (last.num1.contains('.') == false) {
          last.num1 += '.';
        }
        last.operation = Calculations.NONE;
        items.add(last);
      } else if (last.operation == Calculations.ADD) {
        items.add(last);
        items.add(CalcModel(num1: '0.', operation: Calculations.NONE));
      } else if (last.operation == Calculations.MULTIPLY) {
        if (last.num2 == null) {
          last.num2 = last.num2! + '0.';
        } else {
          if (last.num2?.contains('.') == false) {
            last.num2 = last.num2! + '.';
          }
        }
        last.operation = Calculations.MULTIPLY;
        items.add(last);
      }
    } else {
      items.add(CalcModel(num1: '0.', operation: Calculations.NONE));
    }
    return [...items];
  }

  static List<CalcModel> _setClean({required String value, required List<CalcModel> items}) {
    return [];
  }

  static List<CalcModel> _setEqual({required String value, required List<CalcModel> items}) {
    if (items.isNotEmpty) {
      CalcModel last = items.removeLast();
      last.operation = Calculations.EQUAL;
      items.add(last);
    }
    return [...items];
  }

  static List<CalcModel> _setMultiply({required String value, required List<CalcModel> items}) {
    if (items.isNotEmpty) {
      CalcModel last = items.removeLast();
      if (last.closed) {
         if(last.operation == Calculations.ADD && last.num2 != null && last.num2 == '1') {
          last.operation = Calculations.MULTIPLY;
          last.num2 = null;
          last.closed = false;
        }
        items.add(last);
      } else {
        if (last.operation == Calculations.NONE) {
          if (last.num1 != null && last.num1 != '0') {
            last.operation = Calculations.MULTIPLY;
            last.num2 = null;
          }
          items.add(last);
        } else if (last.operation == Calculations.MULTIPLY) {
          if (last.num2!=null && last.num2 != '0') {
            last.closed = true;
          }
          items.add(last);
        } 
      }
    }
    return [...items];
  }

  static List<CalcModel> _setBackward({required String value, required List<CalcModel> items}) {
    if (items.isNotEmpty) {
      items.removeLast();
    }
    return [...items];
  }
}
