#include <iostream>
#include <stdlib.h>

using namespace std;

void initdb();
void menuInsert();
void menuSelect();
void menuUpdate();
void menuDelete();

void insertCategory();
void insertQuestion();

void selectCategory();
void selectQuestion();

void updateCategory();
void updateQuestion();

void deleteCategory();
void deleteQuestion();

void cinClear();

int main()
{
	initdb();

	char choice;
	int exit = 0;
	for(;!exit;){
        choice = 0;
        cout << endl << endl << endl << "Was wollen Sie tun?:" << endl;
        cout << "(e): Daten eingeben" << endl;
        cout << "(a): Daten anzeigen" << endl;
        cout << "(n): Daten aendern" << endl;
        cout << "(l): Daten loeschen" << endl;
        cout << "(s): schliessen" << endl;
        cin >> choice;
        switch(choice){
            case 'e':
                menuInsert();
                break;
            case 'a':
                menuSelect();
                break;
            case 'n':
                menuUpdate();
                break;
            case 'l':
                menuDelete();
                break;
            case 's':
                exit = 1;
                break;
        }
    }
}

void initdb(){
    EXEC SQL CONNECT TO "CSDB@lamp.wlan.hwr-berlin.de" USER gr2 IDENTIFIED BY "2Au-R2n-cQN-uuG";
        cout << "state: " << sqlca.sqlstate << endl;
	EXEC SQL COMMIT;
}

void menuInsert(){
    char choice = 0;
    cout << "Welche Tabelle?:" << endl;
    cout << "(k): Kategorien" << endl;
    cout << "(f): Fragen" << endl;
    cin >> choice;
    switch(choice){
        case 'k':
            insertCategory();
            break;
        case 'f':
            insertQuestion();
            break;
    }
}

void menuSelect(){
    char choice = 0;
    cout << "Welche Tabelle?:" << endl;
    cout << "(k): Kategorien" << endl;
    cout << "(f): Fragen" << endl;
    cin >> choice;
    switch(choice){
        case 'k':
            selectCategory();
            break;
        case 'f':
            selectQuestion();
            break;
    }
}

void menuUpdate(){
    char choice = 0;
    cout << "In welcher Tabelle?:" << endl;
    cout << "(k): Kategorien" << endl;
    cout << "(f): Fragen" << endl;
    cin >> choice;
    switch(choice){
        case 'k':
            updateCategory();
            break;
        case 'f':
            updateQuestion();
            break;
    }
}

void menuDelete(){
    char choice = 0;
    cout << "Aus welcher Tabelle?:" << endl;
    cout << "(k): Kategorien" << endl;
    cout << "(f): Fragen" << endl;
    cin >> choice;
    switch(choice){
        case 'k':
            deleteCategory();
            break;
        case 'f':
            deleteQuestion();
            break;
    }
}

void insertCategory(){
    EXEC SQL BEGIN DECLARE SECTION;
		char eingna[51];
	EXEC SQL END DECLARE SECTION;

	string h = "";
    cout << "Eingabe Name: ";
    getline(cin, h);
    getline(cin, h);

    //cout << h << endl;
    if (!(h.empty()||!strcmp(h.c_str(),"\n")))
    {
        strcpy(eingna, h.c_str());
        EXEC SQL INSERT INTO gr2.test(name) VALUES (:eingna);
        if (!strcmp(sqlca.sqlstate, "23505")) cout << "GIBT'S SCHON" << endl;
        cout << "state: " << sqlca.sqlstate << endl;
        EXEC SQL COMMIT;
    }
}

void  insertQuestion(){
    EXEC SQL BEGIN DECLARE SECTION;
        char question[181];
        char ans0[181];
        char ans1[181];
        char ans2[181];
        char ans3[181];
        int category;
    EXEC SQL END DECLARE SECTION;

    cout << "Frage: ";
    cin >> question;
    cout << "Richtige Antwort: ";
    cin >> ans0;
    cout << "1. Falsche Antwort: ";
    cin >> ans1;
    cout << "2. Falsche Antwort: ";
    cin >> ans2;
    cout << "3. Falsche Antwort: ";
    cin >> ans3;
    cout << "ID der Kategorie:" << endl << "moegliche ";
    selectCategory();
    cin >> category;
    if(category){
        EXEC SQL INSERT INTO gr2.testquestions(question,answer0,answer1,answer2,answer3,category) VALUES (:question,:ans0,:ans1,:ans2,:ans3,:category);
        if(!strcmp(sqlca.sqlstate, "23503")) cout << "Das ist keine gueltige Kategorie!" << endl;
        cout << "state: " << sqlca.sqlstate << endl;
        EXEC SQL COMMIT;
    }
}

void selectCategory(){
    //Die Ausgabe funktioniert nur dann korrekt, wenn die ids eindeutig sind!!!
    EXEC SQL BEGIN DECLARE SECTION;
        int id;
        char name[51];
    EXEC SQL END DECLARE SECTION;

    cout << "Kategorien:" << endl;

	EXEC SQL DECLARE xxx CURSOR FOR SELECT "ID",name FROM gr2.test ORDER BY "ID";
	EXEC SQL OPEN xxx;

    int residl;
	residl = id;

    EXEC SQL FETCH FIRST FROM xxx INTO :id, :name;
	if(!strcmp(sqlca.sqlstate, "00000")) cout << id << " " << name << endl;
	else if(!strcmp(sqlca.sqlstate, "02000")) cout << "Die Tabelle ist leer!";

	while(id != residl)
	{
		residl = id;
		EXEC SQL FETCH NEXT FROM xxx INTO :id, :name;
		if(!strcmp(sqlca.sqlstate, "00000")) cout << id << " " << name << endl;
	}
	EXEC SQL COMMIT;
}

void selectQuestion(){
    //Die Ausgabe funktioniert nur dann korrekt, wenn die ids eindeutig sind!!!
    EXEC SQL BEGIN DECLARE SECTION;
        int id;
        char question[181];
        char ans0[181];
        char ans1[181];
        char ans2[181];
        char ans3[181];
        char cat[51];
    EXEC SQL END DECLARE SECTION;

    string hQuestion = "", hAns0 = "", hAns1 = "", hAns2 = "", hAns3 = "", hCat = "";

    cout << "Fragen:" << endl << endl;

	EXEC SQL DECLARE yyy CURSOR FOR SELECT q."ID",q.question,q.answer0,q.answer1,q.answer2,q.answer3,c.name FROM gr2.testquestions q JOIN gr2.test c ON q."ID" = c."ID" ORDER BY c."ID";
	EXEC SQL OPEN yyy;

    int residl;
	residl = id;

    EXEC SQL FETCH FIRST FROM yyy INTO :id,:question, :ans0, :ans1, :ans2, :ans3, :cat;
	if(!strcmp(sqlca.sqlstate, "00000")){
        hQuestion = question;
        hAns0 = ans0;
        hAns1 = ans1;
        hAns2 = ans2;
        hAns3 = ans3;
        hCat = cat;
        hQuestion.erase(hQuestion.find_last_not_of(" \n\r\t")+1);
        hAns0.erase(hAns0.find_last_not_of(" \n\r\t")+1);
        hAns1.erase(hAns1.find_last_not_of(" \n\r\t")+1);
        hAns2.erase(hAns2.find_last_not_of(" \n\r\t")+1);
        hAns3.erase(hAns3.find_last_not_of(" \n\r\t")+1);
        hCat.erase(hCat.find_last_not_of(" \n\r\t")+1);
        cout << "Schema:" << endl;
        cout << "Frage: Kategorie" << endl << "\tRichtige Antwort" << endl << "\tFalsche Antwort 1" << endl << "\tFalsche Antwort 2" << endl << "\tFalsche Antwort 3" << endl << endl << endl;
        cout << hQuestion << ": " << hCat << endl;
        cout << "\t" << hAns0 << endl;
        cout << "\t" << hAns1 << endl;
        cout << "\t" << hAns2 << endl;
        cout << "\t" << hAns3 << endl;
    }
	else if(!strcmp(sqlca.sqlstate, "02000")) cout << "Die Tabelle ist leer!";

	while(id != residl)
	{
		residl = id;
		EXEC SQL FETCH NEXT FROM yyy INTO :id,:question, :ans0, :ans1, :ans2, :ans3, :cat;
		if(!strcmp(sqlca.sqlstate, "00000")){
            hQuestion = question;
            hAns0 = ans0;
            hAns1 = ans1;
            hAns2 = ans2;
            hAns3 = ans3;
            hCat = cat;
            hQuestion.erase(hQuestion.find_last_not_of(" \n\r\t")+1);
            hAns0.erase(hAns0.find_last_not_of(" \n\r\t")+1);
            hAns1.erase(hAns1.find_last_not_of(" \n\r\t")+1);
            hAns2.erase(hAns2.find_last_not_of(" \n\r\t")+1);
            hAns3.erase(hAns3.find_last_not_of(" \n\r\t")+1);
            hCat.erase(hCat.find_last_not_of(" \n\r\t")+1);
            cout << hQuestion << ": " << hCat << endl;
            cout << "\t" << hAns0 << endl;
            cout << "\t" << hAns1 << endl;
            cout << "\t" << hAns2 << endl;
            cout << "\t" << hAns3 << endl;
        }
	}
	EXEC SQL COMMIT;
}

void updateCategory(){
	EXEC SQL BEGIN DECLARE SECTION;
		int id;
		char name[51];
	EXEC SQL END DECLARE SECTION;
	cout << "Welche Kategorie soll bearbeitet werden? (ID eingeben):" << endl;
	selectCategory();
	cin >> id;
	cout << "Welchen neuen Namen soll die Kategorie bekommen?" << endl;
	cin >> name;
	if(id){
		EXEC SQL UPDATE gr2.test SET name = :name WHERE "ID" = :id;
		if(!strcmp(sqlca.sqlstate, "02000")) cout << "Kein derartiger Datensatz gefunden!";
		EXEC SQL COMMIT;
	}
}

void updateQuestion(){
	EXEC SQL BEGIN DECLARE SECTION;
		int id;
		char question[181];
        char ans0[181];
        char ans1[181];
        char ans2[181];
        char ans3[181];
        int cat;
	EXEC SQL END DECLARE SECTION;
	char choice = 0;
	cout << "Welche Frage soll bearbeitet werden? (ID eingeben):" << endl;
	cin >> id;
	if(id){
		cout << "Was soll an der Frage geaendert werden?" << endl << "(f): Die Fragenstellung" << endl << "(0): Die richtige Antwort" << endl << "(1)-(3): Eine der falschen Antworten" << endl << "(k): Die Kategorie" << endl;
		cin >> choice;
		switch(choice){
			case 'f':
				cout << "Neue Fragenstellung: ";
				cin >> question;
				EXEC SQL UPDATE gr2.testquestions SET question = :question WHERE "ID" = :id;
				break;
			case '0':
				cout << "Neue richtige Antwort: ";
				cin >> ans0;
				EXEC SQL UPDATE gr2.testquestions SET answer0 = :ans0 WHERE "ID" = :id;
				break;
			case '1':
				cout << "Neue falsche Antwort: ";
				cin >> ans1;
				EXEC SQL UPDATE gr2.testquestions SET answer1 = :ans1 WHERE "ID" = :id;
				break;
			case '2':
				cout << "Neue falsche Antwort: ";
				cin >> ans2;
				EXEC SQL UPDATE gr2.testquestions SET answer2 = :ans2 WHERE "ID" = :id;
				break;
			case '3':
				cout << "Neue falsche Antwort: ";
				cin >> ans3;
				EXEC SQL UPDATE gr2.testquestions SET answer3 = :ans3 WHERE "ID" = :id;
				break;
			case 'k':
				cout << "Neue Kategorie (ID):" << endl;
				selectCategory();
				cin >> cat;
				EXEC SQL UPDATE gr2.testquestions SET category = :cat WHERE "ID" = :id;
				break;
		}
		EXEC SQL COMMIT;
	}
}

void deleteCategory(){
	EXEC SQL BEGIN DECLARE SECTION;
		int id;
	EXEC SQL END DECLARE SECTION;
	cout << "Welche Kategorie? (ID)" << endl;
	selectCategory();
	cin >> id;
	if(id){
		EXEC SQL DELETE FROM gr2.test WHERE "ID" = :id;
		if(!strcmp(sqlca.sqlstate, "23503")) cout << "Kategorie kann nicht geloescht werden! (Existieren noch Fragen mit der Kategorie?)" << endl;
		else if(!strcmp(sqlca.sqlstate, "02000")) cout << "Kategorie existiert nicht!" << endl;
		EXEC SQL COMMIT;
	}
}

void deleteQuestion(){
	EXEC SQL BEGIN DECLARE SECTION;
		int id;
	EXEC SQL END DECLARE SECTION;
	cout << "Welche Frage? (ID)" << endl;
	selectCategory();
	cin >> id;
	if(id){
		EXEC SQL DELETE FROM gr2.testquestions WHERE "ID" = :id;
		if(!strcmp(sqlca.sqlstate, "02000")) cout << "Frage existiert nicht!" << endl;
		EXEC SQL COMMIT;
	}	
}

void cinClear() {
	char Muell;
	cin.clear();
	do {
		cin.get(Muell);
	} while (Muell != '\n');
}
