#include "cpp_headers/fcpp.hh"
#include <string.h> // fuer strlen, Laenge eines C-Strings
#define MAX(a,b) a > b ? a : b // gibt stets die groeßere zahl zurueck

// Taschenrechner Stack mit aktuellem Index und Zahlenspeicher
struct RechnerStack {
    int current = 0; // zeigt auf das erste leere Element, anfangs 0
    int numbers[64]; // der Zahlenstack
};

// initialisiere den Stack
RechnerStack stack;

// gibt das letzte Element zurück
int pop() {
    // letztes Element ist eins vor dem ersten leeren
    int last = stack.numbers[stack.current-1];
    // setze den alten Eintrag auf 0
    stack.numbers[stack.current-1] = 0;
    // reduziere den Index um 1, aber falle nicht unter 0
    stack.current = MAX(stack.current-1, 0);
    // gebe letztes Element zurueck
    return last;
}

// fuege ein Element dem Stack hinzu
void push(int element) {
    stack.numbers[stack.current] = element; // setze letztes leeres auf neuen wert
    stack.current += 1; // erhöhe den aktuellen Index
}

int main(int argc, char* argv[]) {
    // Setzen Sie hier auf einen leeren Stack

    // fange kein Kommandozeilenargument ab
    if(argc < 2) {
        print("Eingabe für den Taschenrechner erwartet!");
        return 1;
    }

    // arg enthaelt die als Eingabe von der Kommandozeile uebergebene Zeichenfolge
    char* arg = argv[1];

    // Schleife, die die Zeichen der Eingabe nacheinander ablaeuft
    // strlen gibt die Anzahl der Zeichen in der Zeichenkette
    bool inNumber = false; // merkt, ob aktuell eine zahl eingelesen wird
    int digitCount = 0; // zaehlt die anzahl der ziffern
    for (int i = 0; i <= strlen(arg); i = i+1) {
        char zeichen = arg[i]; // aktuelles Zeichen
        // 48: 0, 49: 1, ..., 57: 9 in ASCII
        if (zeichen >= 48 && zeichen <= 57) {
            inNumber = true; // setze auf true, da gerade Zahl eingelesen wird
            digitCount += 1;
            push(zeichen - 48); // fuege die neue Ziffer dem stack hinzu
        } else if (inNumber) { 
            // erstes Zeichen nach Ziffern, das keine Ziffer ist
            inNumber = false;
            int newNumber = 0; // summiere nun alle ziffern auf
            for (int i = 0; i < digitCount; i++) {
                // nehme ziffer vom stack und multipliziere sie mit der 
                // richtigen Zehnerpotenz fuer diese Dezimalstelle
                newNumber += pop()*pow(10, i);
            }
            // fuege neue Zahl dem Stack hinzu
            push(newNumber);
            // setze Zifferzahl zurueck
            digitCount = 0;
        } if (zeichen == '+' || zeichen == '-' || zeichen == '*' || zeichen == '/') {
            // falls zeichen ein Rechenoperator
            if (stack.current < 2) {
                // nicht genug argumente im stack fuer den operator
                print("Invalid: Not enough arguments for operator!");
                return 1;
            }
            // nehme die zwei letzten Argumente
            int b = pop(); // letztes Element
            int a = pop(); // vorletztes Element
            // und fuehre Operation auf a und b aus, je nach zeichen
            // und fuege sie dem stack hinzu
            if (zeichen == '+') {
                push(a+b);
            } else if (zeichen == '-') {
                push(a-b);
            } else if (zeichen == '*') {
                push(a*b);
            } else if (zeichen == '/') {
                push(a/b);
            }
        }
    }
    if (stack.current > 1) {
        // falls mehr als eine Zahl im Stack uebrig,
        // haben Operatoren gefehlt, werfe also Fehler
        print("Invalid: Not enough operators for argument");
        return 1;
    }
    // drucke das Ergebnis aus (letztes Element auf dem Stack)
    print(pop());
}
