#include "calculator.h"
#include "ui_calculator.h"
#include <QMessageBox>
#include <iostream>
#include <cmath>
using namespace std;
unsigned int index1;
char zeichen;

Calculator::Calculator(QWidget *parent)
    : QMainWindow(parent),
    ui(new Ui::Calculator)
{
    ui->setupUi(this);

    // Connect number buttons to onNumberButtonClicked slot
    connect(ui->button0, &QPushButton::clicked, this, &Calculator::char0);
    connect(ui->button1, &QPushButton::clicked, this, &Calculator::char1);
    connect(ui->button2, &QPushButton::clicked, this, &Calculator::char2);
    connect(ui->button3, &QPushButton::clicked, this, &Calculator::char3);
    connect(ui->button4, &QPushButton::clicked, this, &Calculator::char4);
    connect(ui->button5, &QPushButton::clicked, this, &Calculator::char5);
    connect(ui->button6, &QPushButton::clicked, this, &Calculator::char6);
    connect(ui->button7, &QPushButton::clicked, this, &Calculator::char7);
    connect(ui->button8, &QPushButton::clicked, this, &Calculator::char8);
    connect(ui->button9, &QPushButton::clicked, this, &Calculator::char9);

    // Connect operator buttons to onOperatorButtonClicked slot
    connect(ui->buttonPlus, &QPushButton::clicked, this, &Calculator::charSum);
    connect(ui->buttonMinus, &QPushButton::clicked, this, &Calculator::charSub);
    connect(ui->buttonMultiplication, &QPushButton::clicked, this, &Calculator::charFac);
    connect(ui->buttonDevide, &QPushButton::clicked, this, &Calculator::charDiv);
    connect(ui->buttonKlammern1, &QPushButton::clicked, this, &Calculator::charKlammerAuf);
    connect(ui->buttonKlammern2, &QPushButton::clicked, this, &Calculator::charKlammerZu);
    connect(ui->buttonKomma, &QPushButton::clicked, this, &Calculator::charFloat);

    // Connect equals button to onEqualsButtonClicked slot
    connect(ui->buttonEquals, &QPushButton::clicked, this, &Calculator::berechne);

    // Connect reset button to onEqualsButtonClicked slot
    connect(ui->buttonReset, &QPushButton::clicked, this, &Calculator::clearText);

    // Connect backspace button to onEqualsButtonClicked slot
    //connect(ui->buttonBackspace, &QPushButton::clicked, this, &Calculator::onBackspaceButtonClicked);

    connect(ui->buttonSin, &QPushButton::clicked, this, &Calculator::onSinButtonClicked);
    connect(ui->buttonGrad, &QPushButton::clicked, this, &Calculator::onGradButtonClicked);
    connect(ui->buttonRad, &QPushButton::clicked, this, &Calculator::onRadButtonClicked);
    connect(ui->buttonGon, &QPushButton::clicked, this, &Calculator::onGonButtonClicked);
    connect(ui->buttonPi, &QPushButton::clicked, this, &Calculator::onPiButtonClicked);





}

Calculator::~Calculator()
{
    delete ui;
}

void Calculator::clearText()
{
    ui->textBrowser_2->setPlainText("");
    ui->lineEdit->setText("");
    input="";
}

char Calculator::getZeichen(){
    char result;
    result = input[index1];
    if(index1 <= input.size()-1){
        index1++;
    }else{
        result = ' ';
    }
    return result;
}

double Calculator::calcSin(double result, Sinus::Modus defaultModus){
    double resultRef=result;

    if(defaultModus==Sinus::Modus::grad){
        resultRef=resultRef*pi/180.0;
        resultRef=sin(resultRef);
    }
    else if(defaultModus==Sinus::Modus::bogenmass){
        resultRef=sin(resultRef);
    }
    else if(defaultModus==Sinus::Modus::neugrad){
        resultRef=resultRef * pi/200;
        resultRef=sin(resultRef);
    }

    isSinus=false;

    return resultRef;
}




void Calculator::onPiButtonClicked()
{
    input+="p";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}


void Calculator::onSinButtonClicked()
{
    input+="sin(";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}





void Calculator::onRadButtonClicked()
{
    QString input_qstr = QString::fromStdString(input);
    ui->label_5->setText("Radiant");
    sinus.defaultModus=Sinus::Modus::bogenmass;
}

void Calculator::onGradButtonClicked()
{
    QString input_qstr = QString::fromStdString(input);
    ui->label_5->setText("Grad");
    sinus.defaultModus=Sinus::Modus::grad;
}

void Calculator::onGonButtonClicked()
{
    QString input_qstr = QString::fromStdString(input);
    ui->label_5->setText("Gon");
    sinus.defaultModus=Sinus::Modus::neugrad;
}


void Calculator::char1(){
    input+="1";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char2(){
    input+="2";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char3(){
    input+="3";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char4(){
    input+="4";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char5(){
    input+="5";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char6(){
    input+="6";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char7(){
    input+="7";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char8(){
    input+="8";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char9(){
    input+="9";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::char0(){
    input+="0";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charDiv(){
    input+="/";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charSum(){
    input+="+";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charSub(){
    input+="-";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charFac(){
    input+="*";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charFloat(){
    input+=".";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charKlammerAuf(){
    input+="(";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charKlammerZu(){
    input+=")";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}

void Calculator::charKlammerEckig(){
    input+="]";
    QString input_qstr = QString::fromStdString(input);
    ui->lineEdit->setText(input_qstr);
}





void Calculator::berechne(){
    index1=0;
    zeichen = getZeichen();
    check(zeichen);
    ui->textBrowser_2->append(QString::fromStdString(to_string(ausdruck(zeichen))));

}



//all logic based on 10_10 erweiterung main.cpp
//all logic part of a recursive descent parser for mathematical expressions.
void Calculator::check(char& zeichen){
    string pi="";
    pi +=zeichen;
    string grad="";
    grad+=zeichen;

    if((zeichen <48 || zeichen >57) &&
            zeichen != 'e' &&
            zeichen != '+' &&
            zeichen != '-' &&
            zeichen != '*' &&
            zeichen != '/' &&
            zeichen != '(' &&
            zeichen != ')' &&
            zeichen != '.' &&
            zeichen != ' ' &&
            zeichen != '\n'&&
            zeichen != 's' &&
            zeichen != 'i' &&
            zeichen != 'n' &&
            zeichen != 'R' &&
            zeichen != 'A' &&
            zeichen != 'D' &&
            zeichen != 'G' &&
            zeichen != 'O' &&
            zeichen != 'N' &&
            zeichen != '[' &&
            zeichen != ']' &&
            zeichen != 'p'
            //pi !=      "π"  &grad !=    "°"
            ){

        ui->textBrowser_2->append("Fehlerhaftes Zeichen");
        zeichen = getZeichen();

    }
}



double Calculator::factor(char& zeichen) {
    double result;

    if (zeichen == '(' ) {

        //Oeffnende Klammer ueberspringen
        zeichen = getZeichen();
        check(zeichen);
        result = ausdruck(zeichen); //Rest an ausdruck uebergeben

        if (zeichen != ')'){ //Nach Ausdruck darf hier nur ) kommen
            ui->textBrowser_2->append("rechte Klammer fehlt!");
        }
        else{
            //Schliessende Klammer ueberspringen
            zeichen = getZeichen();
            check(zeichen);
        }
        if(isSinus){
            result = calcSin(result, sinus.defaultModus);
        }
    }
    else{ //Wenn kein Klammerausdruck, kann hier nur Zahl kommen
        result = zahl(zeichen);
    }
    return result;
}






double Calculator::zahl(char& zeichen) {
    double result = 0;
    string zeichenRef="";
    zeichenRef+=zeichen;

    while (isdigit(zeichen)) {

        result = 10 * result + long(zeichen - '0');


        zeichen = getZeichen();
        check(zeichen);
    }
    if (zeichen == '.') {

        zeichen = getZeichen();
        check(zeichen);
        double nachkommastelle = 1.0;
        while (isdigit(zeichen)) {
            nachkommastelle *= 10.0;
            result = result + double(zeichen - '0') / nachkommastelle;

            zeichen = getZeichen();
            check(zeichen);
        }
    }
    if(zeichen == 'p'){
        result=pi;
        zeichen=getZeichen();
        check(zeichen);
    }
    if(zeichen == 's'){
        isSinus=true;
        zeichen=getZeichen();
        zeichen=getZeichen();
        zeichen=getZeichen();
        check(zeichen);
        result=ausdruck(zeichen);
    }


    return result;
}


double Calculator::ausdruck(char& zeichen) {
    string zeichen_str="";
    zeichen_str+=zeichen;
    double result; // Hilfsvariable für Ausdruck
    if (zeichen == '-') {
        zeichen = getZeichen();
        // - überspringen und zum nächsten zeichen[i] gehen
        check(zeichen);
        result = -summand(zeichen); // Rest an summand() übergeben
    } else {
        if (zeichen == '+'){
            // + überspringen und zum nächsten zeichen[i] gehen
            zeichen = getZeichen();
            check(zeichen);
        }
        result = summand(zeichen);
    }
    while (zeichen == '+' || zeichen == '-'){
        if (zeichen == '+') {
            zeichen = getZeichen();
            check(zeichen);
            result += summand(zeichen);
        } else {
            zeichen = getZeichen();
            check(zeichen);
            result -= summand(zeichen);
        }
    }
    return result;
}






double Calculator::summand(char& zeichen) {
    double tmp;
    double result = factor(zeichen);
    while (zeichen == '*' || zeichen == '/') {
        if (zeichen == '*') {
            // * überspringen
            zeichen = getZeichen();
            check(zeichen);
            result *= factor(zeichen);
        } else {
            // / überspringen
            zeichen = getZeichen();
            check(zeichen);
            tmp = factor(zeichen);
            if (tmp == 0)
                ui->textBrowser_2->append("Division durch 0 nicht möglich!");
            else
                result /= tmp;
        }
    }
    return result;
}