#include "LE.h"

// listi.cc:61: Fehler: Abfrage des Elementes »setNext« in »liste1«, das vom Nicht-Klassentyp »LE*« ist
// man braucht -> und nicht "." weil zeiger dinger nicht mit "." gehen


#include <strings.h>
#include <string.h>
#include <regex.h>

#include "LE.h"

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

int match(const char *string, char *pattern);

int main(int argc, char** argv) {

    //Immer Zeiger weil da bei C++ halt so ist
    //LE* lol = new LE();
    //cout << lol->getNuDa() << endl;
    //lol->setNuDa("hallo");
    //cout << lol->getNuDa() << endl;

    LE* head = NULL;
    LE* tail = NULL;

    int toggle = 0;
    char cmd[100];

    while (1) {

        printf("\nMenue:\n"
                "1  Neues Element am Anfang der Liste einfuegen\n"
                "2  Neues Element am Ende der Liste einfuegen\n"
                "3  Nach einem String suchen\n"
                "4  Ein neues Element nach einem gegebenen Element einfuegen\n"
                "5  Ein Element loeschen\n"
                "6  Ganze Liste loeschen\n"
                "7  Elemente der Liste Zaehlen\n"
                "8  Zyklisch <--> Azyklisch umwandeln\n"
                "Q  Programm beenden\n\n  Eingabe: ");

        scanf("%s", cmd);

        if (match(cmd, (char*) "^[1-8qQ]{1}$") != 1) {
            printf("\nFehler, ungueltige Eingabe!\n\n");
        }

        if (strcasecmp(cmd, "1") == 0) {
            printf("\nFuege neues Element am Anfang der Liste ein\n\n");
            LE* liste1 = new LE();

            char eingabe[100];

            printf("Nutzdaten: ");
            scanf("%s", eingabe);
            liste1->setNuDa(eingabe);

            if (head == NULL) { //Liste ist noch leer
                head = liste1;
                tail = liste1;

                liste1->setPrev(NULL);
                liste1->setNext(NULL);
            } else { //Element hinzufuegen
                if (tail == head->getPrev()) { //Liste ist zyklisch

                    liste1->setNext(head);
                    liste1->setPrev(tail);

                    tail->setNext(liste1);

                    head->setPrev(liste1);

                    head = liste1;
                } else {
                    liste1->setNext(head);
                    liste1->setPrev(NULL);
                    head->setPrev(liste1);
                    head = liste1;
                }

            }
        }

        if (strcasecmp(cmd, "2") == 0) {
            printf("\nFuege neues Element am Ende der Liste ein\n\n");
            LE* liste1 = new LE();

            char eingabe[100];

            printf("Nutzdaten: ");
            scanf("%s", eingabe);
            liste1->setNuDa(eingabe);

            if (head == NULL) { //Liste ist noch leer
                head = liste1;
                tail = liste1;

                liste1->setPrev(NULL);
                liste1->setNext(NULL);
            } else { //Element hinzufuegen
                if (tail == head->getPrev()) { //Liste ist zyklisch

                    liste1->setNext(head);
                    liste1->setPrev(tail);

                    tail->setNext(liste1);

                    head->setPrev(liste1);

                    tail = liste1;
                } else {
                    liste1->setNext(NULL);
                    liste1->setPrev(tail);
                    tail->setNext(liste1);
                    tail = liste1;
                }
            }
        }

        if (strcasecmp(cmd, "3") == 0) {
            char eingabe[100];
            LE* curAdr = new LE();
            LE* temp = tail;

            int i = 1;
            int gefunden = 0;

            printf("\nSuche nach String: ");
            scanf("%s", eingabe);

            curAdr = head;
            while (curAdr != NULL) {
                if (curAdr->getNuDa() == eingabe) {
                    printf("\nString \"%s\" im %d. Listenelement gefunden\n", eingabe, i);
                    gefunden = 1;
                }
                curAdr = curAdr->getNext();
                i++;

                if (curAdr == temp) { //Dann bin ich im am ende
                    if (curAdr->getNuDa() == eingabe) {
                        printf("\nString \"%s\" im %d. Listenelement gefunden\n", eingabe, i);
                        gefunden = 1;
                    }
                    break;
                }
            }

            if (gefunden != 1) {
                printf("\nString \"%s\" NICHT gefunden\n", eingabe);
            }
        }

        if (strcasecmp(cmd, "4") == 0) {
            char eingabe[100];
            char nuda[100];
            LE* curAdr = new LE();
            int gefunden = 0;

            printf("\nName des Elements nach dem eingefuegt werden soll: ");
            scanf("%s", eingabe);

            printf("\nNutzdaten: ");
            scanf("%s", nuda);

            LE* temp = tail;
            curAdr = head;
            while (curAdr != NULL) {
                if (curAdr->getNuDa() == eingabe) {
                    LE* neu = new LE();
                    gefunden = 1;
                    neu->setNuDa(nuda);

                    if (curAdr == tail) {
                        printf("\nOh, ein Sonderfall!\n");
                        if (tail == head->getPrev()) { //Liste ist zyklisch
                            neu->setNext(head);
                            neu->setPrev(curAdr);

                            curAdr->setNext(neu);

                            head->setPrev(neu);

                            tail = neu;
                            break;

                            if (curAdr == temp) { //Dann bin ich im am ende
                                neu->setNext(head);
                                neu->setPrev(curAdr);

                                curAdr->setNext(neu);

                                head->setPrev(neu);

                                tail = neu;

                                break;
                            }


                        } else { //Liste ist azyklisch
                            neu->setNext(NULL);
                            neu->setPrev(curAdr);

                            tail = neu;

                            curAdr->setNext(neu);
                            break;
                        }
                    } else { //Nicht nach dem letzten Element
                        neu->setNext(curAdr->getNext());
                        neu->setPrev(curAdr);

                        curAdr->getNext()->setPrev(neu);

                        curAdr->setNext(neu);
                        break;
                    }
                }
                curAdr = curAdr->getNext();

                if (curAdr->getPrev() == temp) { //Dann bin ich im am ende
                    break;
                }


            }

            if (gefunden != 1) {
                printf("\nString \"%s\" NICHT gefunden\n", eingabe);
            }
        }

        if (strcasecmp(cmd, "5") == 0) {
            char eingabe[100];
            LE* curAdr = new LE();
            int i = 1;
            int gefunden = 0;

            printf("\nName des zu loeschenden Listenelements: ");
            scanf("%s", eingabe);

            LE* temp = tail;
            curAdr = head;
            while (curAdr != NULL) {
                if (curAdr->getNuDa() == eingabe) {
                    if (curAdr == tail || curAdr == head) {
                        printf("\nOh, ein Sonderfall!\n");
                        if (tail == head->getPrev()) { //Liste ist zyklisch
                            if (curAdr == tail) {
                                curAdr->getPrev()->setNext(head); //Das neue letzte Element zeigt auf das erste
                                head->setPrev(curAdr->getPrev());
                                tail = curAdr->getPrev();
                                break;
                            }

                            if (curAdr == head) {
                                curAdr->getNext()->setPrev(tail);
                                tail->setNext(curAdr->getNext());
                                head = curAdr->getNext();
                                break;
                            }

                        } else {
                            if (curAdr == tail) {
                                curAdr->getPrev()->setNext(NULL);
                                tail = curAdr->getPrev();
                                break;
                            }

                            if (curAdr == head) {
                                curAdr->getNext()->setPrev(NULL);
                                head = curAdr->getNext();
                                break;
                            }
                        }

                    } else {
                        curAdr->getPrev()->setNext(curAdr->getNext());
                        curAdr->getNext()->setPrev(curAdr->getPrev());
                        break;
                    }
                    delete curAdr;

                    gefunden = 1;
                }
                curAdr = curAdr->getNext();
                i++;

                if(curAdr->getPrev() == temp){
                //if (curAdr == temp) { //Das letzte Element
                    break;
                }
            }

            if (gefunden != 1) {
                printf("\nString \"%s\" NICHT gefunden\n", eingabe);
            }
        }

        if (strcasecmp(cmd, "6") == 0) {
            printf("\nLoesche ganze Liste\n\n");
            LE* curAdr = new LE();
            LE* start = new LE();

            start = head;
            curAdr = head;

            while (curAdr != NULL) {

                if (curAdr != head) {
                    delete curAdr->getPrev();
                }

                curAdr = curAdr->getNext();

                if (curAdr == start) { //Bin einmal durch, auch bei zyklisch
                    break;
                }
            }

            head = NULL;
            tail = NULL;
        }

        if (strcasecmp(cmd, "7") == 0) {
            int i = 1;
            LE* curAdr = new LE();

            LE* temp = tail;

            curAdr = head;

            while (curAdr != NULL) {

                if (curAdr != head) {
                    i++;
                }

                curAdr = curAdr->getNext();

                if (curAdr == temp) { //Dann bin ich im am ende
                    i++;
                    break;
                }

            }

            printf("\nDie Liste hat %d Element(e)\n\n", i);
        }

        if (strcasecmp(cmd, "8") == 0) {
            printf("\nWandle Zyklisch <--> Azyklisch um\n\n");


            if (toggle == 0) {
                head->setPrev(tail);
                tail->setNext(head);
                toggle = 1;
            } else {
                head->setPrev(NULL);
                tail->setNext(NULL);
                toggle = 0;
            }
        }

        if (strcasecmp(cmd, "Q") == 0) {
            printf("\nProgrammende\n\n");
            return (EXIT_SUCCESS);
        }

        //Liste ausgeben
        int i = 0;
        printf("\nAktuelle Liste:\n\nVorg. Ad.:\tAdresse:\tNachf. Ad.:\tNutzdaten:\n");
        printf("\t\t  Head\t\t  %06x\n", head); //Adresse auf die head zeigt ausgeben


        // LE* temp = head; //geht nicht weil zyklisch ja nie auf head zeigt
        //muss erstes oder letzte element speichern oder so

        LE* temp = tail;
        LE* test = head;

        while (test != NULL) {
            printf(" %06x\t\t %06x\t\t  %06x\t%s\n", test->getPrev(), test, test->getNext(), test->getNuDa().c_str());
            test = test->getNext();

            if (test == temp) { //Dann bin ich im am ende
                //noch das aktuelle Element ausgeben, dann raus
                printf(" %06x\t\t %06x\t\t  %06x\t%s\n", test->getPrev(), test, test->getNext(), test->getNuDa().c_str());
                break;
            }
        }

        printf(" %06x\t\t  Tail\n", tail); //Adresse auf die tail zeigt ausgeben

    }

    return (EXIT_SUCCESS);
}

int match(const char *string, char *pattern) {
    int status;
    regex_t re;
    if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
        return (0); /* report error */
    }
    status = regexec(&re, string, (size_t) 0, NULL, 0);
    regfree(&re);
    if (status != 0) {
        return (0); /* report error */
    }
    return (1);
}