#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include "calculator.h"

LiquidCrystal_I2C lcd(0x27, 16, 2);

char customkey;
const byte rows = 4;
const byte cols = 4;

char keys[rows][cols]= {
  {'1','2','3','+'},
  {'4','5','6','-'},
  {'7','8','9','*'},
  {'C','0','=','/'}
};

byte ROWSpins[rows] = {9,8,7,6};
byte COLSpins[cols] = {5,4,3,2};

Keypad customKeypad = Keypad(makeKeymap(keys), ROWSpins,COLSpins, rows,cols);

const byte OPERATORSCOUNT = 4;
const byte EQUITIONSCOUNT = 32;

const unsigned char* OPERATORS = "/*-+";

byte equition;
String number;
Calculator equitions[EQUITIONSCOUNT*2+1], total;

Calculator calculator(){
  
  byte position = 0;
  Calculator result;

  calculate:

  position%=equition;

  if (equitions[position] == *OPERATORS) {
    result = equitions[position](equitions[position-1], equitions[position+1]);
    for(int i=-1; i<2; i++) equitions[position-i] = result;
  }

  if (++position==equition) OPERATORS++;
  if (*OPERATORS) goto calculate;

  OPERATORS-=OPERATORSCOUNT;

  return result;

}

bool isNegative(){
  if (equitions[equition]=='\0') {Serial.println("num: "+String(equitions[equition]())); return 0;}
  if (customkey=='-') {
    lcd.print('(');
    number += '-';
    return true;
  }
  return false;
}

void CheckNumber (){
  if (number) {
    equitions[equition](number);
    if (equitions[equition]() < 0) lcd.print(')');
    number = "";
  }
}

void ShowAnsower (){
  lcd.setCursor(0, 1);
  lcd.print("Ans = ");
  lcd.print(total(), 6);
}

void ClearEquition(){
  for(int i=0;i<equition;i++) equitions[i] = Calculator();
  equition=0;
  number="";
}

void ClearScreen(){
  lcd.clear();
  lcd.setCursor(0, 0);
}


void setup(){

  lcd.init();
  lcd.backlight();  

  ClearScreen();

  lcd.print("Hesap Makinesi");
  lcd.setCursor(0,1);
  lcd.print("Sayi Giriniz:");
  delay(1750);

  ClearScreen();

  Serial.begin(9600);

}

void loop(){

  customkey = customKeypad.getKey();

  switch(customkey){

    case '0' ... '9':
      number += customkey;
      lcd.print(customkey);
    break;

    case '/': case '*': case '-': case '+':
      CheckNumber();
      if (isNegative());
      else equitions[(++equition)++](customkey);
      lcd.print(customkey);
    break;

    case '=':
      CheckNumber();
      total = calculator();
      ShowAnsower();
    break;

    case 'C':
      ClearScreen();
      ClearEquition();
  }

  delay(10);

}