#include "programManager.h"


ProgramManager::ProgramManager()
    : nextThread(0)
{

}

ProgramManager::~ProgramManager()
{
    for(auto e : threadList) {
        delete e->pageManager;
        delete e;
        e = nullptr;
    }
}

int ProgramManager::start(Settings *settings)
{
    pageManager.setDebugMode(settings->debugMode);
    pageManager.setProxy(settings->proxy_ip, settings->proxy_port);
    if(dirExists(settings->cookieFilePath)) {
        std::cout << " => Error: Kann Cokkie-File nicht erstellen: \n           '"
                  << settings->cookieFilePath << "'." << std::endl;
        return 174;
    }

    //Überprüfe letzte Update suche
    if(settings->modus != Modus::UPDATE_MODUS )
        if( checkLastProgrammUpdate(settings) )
            return 175;

    switch (settings->modus) {
    case Modus::DEFAULT_MODUS:
        return defaultModus(settings);
    case Modus::DIRECT_LINK_MODUS:
        return directLinkModus(settings);
    case Modus::SEARCH_MODUS:
        return searchModus(settings);
    case Modus::INFO_MODUS:
        return infoModus(settings);
    case Modus::NEWS_MODUS:
        return newsModus(settings);
    case Modus::UPDATE_MODUS:
        return updateModus(settings);
    case Modus::REMOVE_SETTINGS_AND_CACHE_MODUS:
        return cleanUpSettingsAndCache(settings);
    case Modus::POPULAR_MODUS:
        return printPopularSeries(settings);
    default:
        std::cout << " => Error: Keine Unteroption ausgewählt." << std::endl;
        return -1;
    }
}


void * threadFunction(void * data) {
    ThreadData * myThreadData = reinterpret_cast<struct ThreadData*>(data);
    myThreadData->returnValue="";
    myThreadData->exitState=0;


    Reply tmp_reply = myThreadData->pageManager->getServerRequest( myThreadData->page.protocol, myThreadData->page.url + myThreadData->page.UrlDir + myThreadData->nameInUrl
                                                          + "/staffel-" + std::to_string(myThreadData->staffel) + "/episode-" + std::to_string(myThreadData->folge));
    if(tmp_reply.html == "-1") {
        if(myThreadData->settings->debugMode)
            std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": getServerRequest Function reurns -1." << std::endl;
        return myThreadData->setState(10);
    }
    std::string allLinks = myThreadData->pageManager->getLinks(tmp_reply.html);
    std::string Link = myThreadData->pageManager->chooseHosterLink(allLinks, myThreadData->settings->genaueHoster, myThreadData->settings->languages, myThreadData->settings->debugMode);

    if(myThreadData->settings->debugMode)
        std::cout  << " > Thread " << myThreadData->id << allLinks << std::endl << ( (Link == "") ? "" : " -> Link: 'https://" + myThreadData->page.url) << Link << ( (Link == "") ? "" : "'\n" );




    std::string folgenID = std::string((myThreadData->staffel == -1 || myThreadData->folge == -1 ) ? "" : "S"
                                        + std::string( (myThreadData->staffel < 10) ? "0" : "" ) + std::to_string(myThreadData->staffel)
                                                                            + "E" + std::string( (myThreadData->folge   < 10) ? "0" : "" ) + std::to_string( myThreadData->folge ) );
    std::string green = ((myThreadData->settings->colorless) ? "" : "\033[32m"),
                red = ((myThreadData->settings->colorless) ? "" : "\033[31m"),
                orange =((myThreadData->settings->colorless) ? "" : "\033[33m"),
                blue = ((myThreadData->settings->colorless) ? "" : "\033[34m"),
                clearColor = ((myThreadData->settings->colorless) ? "" : "\033[0m");

    if(Link == "") {
        //Wenn gar keine Links vorhanden sind:
        if(allLinks == "") {
            myThreadData->returnValue = " => " + red + "KEINEN Hoster für die Folge " + replace(folgenID, "E", " E") + " gefunden." + clearColor;
            if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths, std::string("KEINEN Hoster für die Folge ")
                                                      + replace(folgenID, "E", " E") + std::string(" gefunden.")) != 0) {
                if(myThreadData->settings->debugMode)
                    std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl;
                return myThreadData->setState(14);
            }
        //Wenn nur kein passender Link gefunden wurde:
        } else {
            myThreadData->returnValue = " => " + orange + "Keinen PASSENDEN Hoster für die Folge " + replace(folgenID, "E", " E") + " gefunden." + clearColor + "\n"
                      + "Alle Links:" + "\n"
                      + replace(
                        replace( replace( allLinks, "data-lang-key=\"1\"", "language=\"GerDub\"" ),
                                                                   "data-lang-key=\"2\"", "language=\"Eng\"" ), "data-lang-key=\"3\"", "language=\"GerSub\"");
            if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths,
                                                      std::string("Keinen PASSENDEN Hoster für die Folge ") + replace(folgenID, "E", " E")
                                                      + std::string(" gefunden.")) != 0) {
                if(myThreadData->settings->debugMode)
                    std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl;
                return myThreadData->setState(15);
            }
        }

        if(myThreadData->settings->debugMode)
            std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": closeThread, no (good) Link was found." << std::endl;
        return myThreadData->setState(0);
    }

    for (int i = 1; i <= 3; ++i) {
        auto REPLy = myThreadData->pageManager->getUrlAfterRedirect( myThreadData->page.protocol, myThreadData->page.url + Link, myThreadData->settings->cookieFilePath +  "_" + myThreadData->page.url + std::to_string(myThreadData->id));
        std::string newUrl = REPLy.url;
        if (newUrl == "-1") {
            if(myThreadData->settings->debugMode)
                std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": getUrlAfterRedirect Function failed: returned -1." << std::endl;
            return myThreadData->setState(16);

            // Get redirect link after getUrlAfterRedirect function
        } else if (newUrl == "https://s.to" || newUrl == "http://190.115.18.20/" || newUrl == "https://" + myThreadData->page.url || REPLy.html.find("404 - Seite nicht gefunden") != std::string::npos || REPLy.html.find("403 Forbidden") != std::string::npos) {
            if(myThreadData->settings->debugMode)
                std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": getUrlAfterRedirect Function failed: 404 - Seite nicht gefunden oder 403 Forbidden." << std::endl;
            return myThreadData->setState(404);

        } else if(newUrl.find("/redirect/") != std::string::npos ) {
            if(myThreadData->settings->debugMode)
                std::cout  << " > Thread " << myThreadData->id << "Warnung: Redirect Link nach umwandlung (Capcha?) --> Neuer Account" << std::endl;
            if(myThreadData->pageManager->login(myThreadData->page, myThreadData->accountManager->getNextAccount(), myThreadData->settings->cookieFilePath  +  "_" + myThreadData->page.url + std::to_string(myThreadData->id)) != 0) {
                if(myThreadData->settings->debugMode)
                    std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": login Function failed." << std::endl;
                return myThreadData->setState(17);
            }
            continue;

            // get NO-Redirect Link after getUrlAfterRedirect Function
         } else {
            if( (newUrl = myThreadData->pageManager->getLinkAfterHosterBasedOperation(newUrl)) == "") {
                if(myThreadData->settings->debugMode)
                    std::cout << " => Error in getLinkAfterHosterBasedOperation() -> exit threadFunction()" << std::endl;
                return myThreadData->setState(22);
            }

            myThreadData->returnValue = " => " + folgenID + ( (folgenID == "") ? "" : ": " ) + green + newUrl + clearColor;
            if(myThreadData->settings->outputFilePaths.size() != 0) {
                if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths,folgenID + ( (folgenID == "") ? "" : ": " ) + newUrl) != 0) {
                    if(myThreadData->settings->debugMode)
                        std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl;
                    return myThreadData->setState(18);
                }
            }
            if(myThreadData->settings->debugMode)
                std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": get a NO Redirect Link after function: Good! => return 0." << std::endl;
            return myThreadData->setState(0);
        }
    }

    //error at 3 time
    myThreadData->returnValue = " => " + replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + red + "https://" + myThreadData->page.url + Link + clearColor;
    if(myThreadData->settings->outputFilePaths.size() != 0)
        if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths, replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + Link) != 0) {
            if(myThreadData->settings->debugMode)
                std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl;
            return myThreadData->setState(19);
        }
    if(myThreadData->settings->debugMode)
        std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": 3 Times to convert fails, but return 0." << std::endl;
    return myThreadData->setState(0);

}

int ProgramManager::waitForThreads()
{
    for( auto &e : threadList) {
        if( e->exitState != -1 && pthread_join(e->thread, nullptr) == 0) {
            if(e->exitState != 0) {
                std::cout << "\33[2K\r => Error: Thread gab error zurück." << std::endl;
                return e->exitState;
            } else
                if(e->returnValue != "")
                    std::cout << ("\33[2K\r(T" + std::to_string(e->id) + ")" + e->returnValue ) << std::endl;
        }
        e->exitState = -1;
        e->returnValue = "";
        e->setData(0, 0);
        e->thread = 0;
    }



    return 0;
}

int ProgramManager::sucheNach_1_Serien(Settings *settings, PageManager &pageManager, checkNameRply &newNameAndPage)
{
    std::string finds;
    std::string gewollteSeitenUrl;
    int NO_ERROR_BUT_EXIT_RETURN = -10101;

    if(settings->pagesInUse.size() < 1) {
        std::cout << " => Error Keine Internet Seiten vorhanden." << std::endl;
        return 1290;
    }

    //Führe unterfunction zum suchen von Serien aus, aber ohne suche auszugeben und speichere datein in variable
    if(searchModus(settings, &finds, true) != 0) {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Function searchModus returned error." << std::endl;
        return 24;

    } else if( finds == "" ) {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": ERROR:?? searchModus's returnValue = '' => Nothing found!" << std::endl;


        return NO_ERROR_BUT_EXIT_RETURN;
    }
    // Wenn der Rückgabe wert ungültig ist brich ab...
    else if( finds.find("|/") == std::string::npos ) { // ||
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": searchModus's returnValue contains no / or | => error " << std::endl;

        return 121; // error -10101 (NO_ERROR_BUT_EXIT_RETURN);

    // Wenn der Rückgabewert mehrene newlines enthält gibt es mehrere Möglichkeiten
    } else if (finds.find("\n") != std::string::npos) {

        //Gib alle gefundenen Serien Zeilenweise aus und schreibe davor die Zeile:
        std::stringstream myStrStream(finds + "\n");
        std::string line;

        std::cout << "\nWähle eine der folgenden Serien, oder nur [Enter] um Forgang abzubrechen." << std::endl;
        std::string lastPage = "";
        for (unsigned i = 1; std::getline(myStrStream, line).good() ; ++i) {
            if(line.find_last_of("|") == std::string::npos) {
                std::cout << " => Error: Invalid Line: " << line << std::endl;
                return -21;
            }

            std::string pageUrl = line.substr( line.find_last_of('|') + 1);
            //gib neue Internet seite aus, wenn sie noch  nicht ausgegeben wurde
            if( lastPage != pageUrl) {
                std::cout << "\n-> Auf '" << pageUrl << "':" << std::endl;
                lastPage = pageUrl;
            }
            line.erase(line.find_last_of('|'));

            if(line.find_last_of("|") == std::string::npos) {
                std::cout << " => Error: Invalid Line: " << line << std::endl;
                return -21;
            }
            std::cout << "[" << i << "]: " << line.substr(line.find_last_of("|")  + 1) << ( (settings->search_show_othernames && line[0] != '|') ? " ( " + line.substr(0, line.find("|")) + " )" : "" ) << std::endl;
        }

        //Lass Benutzer Zeile auswählen:
        std::cout << "\nNummer: " << std::flush;
        std::string input;
        std::getline(std::cin, input);

        //Wenn kein Input, brich ab
        if(input == "") {
            std::cout << " => Abbruch..." << std::endl;
            return NO_ERROR_BUT_EXIT_RETURN;
        }

        //Wähle Zeile aus
        myStrStream.clear();
        myStrStream.str(finds + "\n");
        bool hasNewName = false;

        //Geh die Liste nochmal durch
        for (unsigned i = 1; std::getline(myStrStream, line).good() ; ++i) {
            if(line.find_last_of("|") == std::string::npos) {
                std::cout << " => Error: Invalid Line: " << line << std::endl;
                return -22;

                // Wenn die Zeile gleich der ausgewählten ist:
            } else if(static_cast<int>(i) == atoi(input.c_str()) ) {
                //entferne und speichere PageUrl;
                gewollteSeitenUrl = line.substr(line.find_last_of('|') + 1);
                line.erase(line.find_last_of('|'));

                //Speichere den Namen der Serie und setzte hasName auf true und brich schleife ab
                if ( (finds = line.substr( line.find("|/") + 2, // beginn: nach dem |/
                                           line.find("|", line.find("|/") + 2) // Bis zu dem | ab dem ende von |/
                                           - line.find("|/") -2) ) == "" ) { // wegen nicht bi sondern länge, suptrahiere Pos 1
                    std::cout << " => Error: Konnte den Namen aus der zurückgegebenen Zeile nicht extrahieren. In ausWahlVariante" << std::endl;


                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Return value from searchModus.subStr(pos(/)-> next |, after /) is ''." << std::endl;
                    return 48;
                }
                hasNewName = true;
                break;
            }
        }
        //Wenn keine der Zeilen gelcih dem Input war, input invali -> brich ab...
        if(!hasNewName) {
            std::cout << " => Error: Ungültige Eingabe: '" << input << "'" << std::endl;
            return  123;
        }

        //Wenn nur 1 Serie gefunden wurde:
    } else {
        //entferne und speichere PageUrl;
        gewollteSeitenUrl = finds.substr(finds.find_last_of('|') + 1);
        finds.erase(finds.find_last_of('|'));

        //Frag den User ob das die Richtige Serie ist:
        std::cout << " -> Ist das deine gewünschte Serie: '"
                  << finds.substr(finds.find_last_of("|")  + 1) << "'" << ( (finds[0] != '|' && settings->search_show_othernames) ? " ( " + finds.substr(0, finds.find("|")) + " )" : "" ) << std::endl
                  << "Drücke nur [Enter] um fortzufahren: " << std::flush;

        std::string line;
        std::getline(std::cin, line);

        //Wenn input => abbruch
        if ( line != "") {
            std::cout << " => Abbruch..." << std::endl;
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": User tipped an Value => wrong serie." << std::endl;
            return NO_ERROR_BUT_EXIT_RETURN;
        }

        //Überschreibe eine Zeile mit nur dem url Namen
        if ( (finds = finds.substr( finds.find("|/") + 2, finds.find("|", finds.find("|/") + 2) - finds.find("|/") -2) ) == "" ) {
            std::cout << " => Error: Konnte den Namen aus der zurückgegebenen Zeile nicht extrahieren." << std::endl;
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": Return value from searchModus.subStr(pos(/)-> next |, after /) is ''." << std::endl;
            return 46;
        }

    }

    //suche Seite aus sucheregbnis in settings...
    bool found = false;
    for ( const auto & page : settings->pagesInUse ) {
        if( page.name_id == gewollteSeitenUrl || page.url == gewollteSeitenUrl) {
            newNameAndPage.pageInUse = page;
            found = true;
        }
    }
    if( !found ) {
        std::cout << " => Error: Konnte '" << gewollteSeitenUrl << "' nicht als Valide Seite erkennen!"  << std::endl;
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ":failed to search url in pagesList from setings object" << std::endl;
        return 45;
    }


    //Überprüfe ob es die serie gibt wenn ja speicher ihn in newname und beende Function
    //test jetzt nicht mehr alle seiten, sondern die die ausgewählt wurde!!!!!
    std::vector<PAGE> pages;
    pages.push_back( newNameAndPage.pageInUse );

    auto ret = pageManager.checkName( pages  /*settings->pages dann glaub
                                   ich immer fehler, wenn serie auf 2 seiten excistiert*/,
                                      finds,  settings->useFirstPage, settings->outputFilePaths, settings->default_checkPath );
    if(ret.status == ret.FAILED || ret.status == ret.MULTIPLE_OPTIONS)
        return 23;
    else if( ret.status == ret.NOTHING_FOUND ) {
            std::cout << " => Error: Konnte die von der Suche vorgeschlagene Serie nicht finden." << std::endl;
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": Extracted Name from searchModus is invalid." << std::endl;
            return 47;
    }  else if( ret.status == ret.NO_WORKING_PAGE ) {
        std::cout << " => Error: Keine Funktionierende Internetseite!" << std::endl;
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ":  Keine Funktionierende Internetseite!" << std::endl;
        return 0;

    } else {
        //speichere neuen Namen in übergebenen ref var
        newNameAndPage.name = ret.name;
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Use new SerienName: '" << ret.name << "'." << std::endl;
        return 0;
    }
}


int ProgramManager::checkLastProgrammUpdate(Settings *settings)
{
    //Wenn die Funktion deaktiviert ist brich ab, wenn nicht nur diffdays verlangt wird
    if(settings->programmUpdateWarningDays == 0) {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": In settings:  Programm --- upDateWaring is deaktivated(seted to 0)." << std::endl;
        return 0;
    }

    std::ifstream ifs(settings->lastProgrammUpdateDateFilePath);
    if(!ifs.is_open()) {
        std::ofstream ofs2(settings->lastProgrammUpdateDateFilePath);
            if(!ofs2.is_open()) {
                perror(("Konnte die Datei '" + settings->lastProgrammUpdateDateFilePath + "' nicht öffnen").c_str());
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": Failed to create Last Programm Update Date File:'" << settings->lastProgrammUpdateDateFilePath << "'." << std::endl;
                return 1;
            } else {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": Ordfolgreich Last Programm UpdateTime Save File erstellt:'" << settings->lastProgrammUpdateDateFilePath << "'." << std::endl;
                ofs2 << "0" << std::endl;
                ofs2.close();
                ifs.open(settings->lastProgrammUpdateDateFilePath);
                if(!ifs.is_open()) {
                    perror(("Konnte die Datei '" + settings->lastProgrammUpdateDateFilePath + "' nicht öffnen").c_str());
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Failed to open Last Programm Update Date File:'" << settings->lastProgrammUpdateDateFilePath << "'." << std::endl;
                    return 4545;
                }
            }
    }
    std::string line;
    ssize_t difDays = 0;
    if(!std::getline(ifs, line).good()) {
        perror("GetLine from Date failed");
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Get the first Line of the Last Programm  UpdateDate File failed." << std::endl;
        return 2;

    } else if( ( ( difDays = static_cast<long long>(pageManager.getDate()) - atoll(line.c_str()) )) >= settings->programmUpdateWarningDays) {
        //Gib nachricht nicht aus wenn nur diffday verlangt wird
        if( true ) {
            std::cout << ((settings->colorless) ? "" : "\033[93m") << " => Warnung: Eine Überprüfung auf Updates wurde zuletzt vor " << difDays << " Tagen durchgeführt!"
                      << std::endl << "             Wollen sie nach updates suchen? (Y/n): " << ((settings->colorless) ? "" : "\033[0m") << std::flush;
            std::cin.clear();
            std::string inp;
            std::getline(std::cin, inp);

            if(inp == "" || inp == "Y" || inp == "y" || inp == "j" || inp == "J") {
                std::string program = settings->argv0.substr(0, //ganzer pfad
                            settings->argv0.substr(
                                                                 settings->argv0.find_last_of(settings->pathSymbol) == std::string::npos ? 0 : settings->argv0.find_last_of(settings->pathSymbol)
                                                   ) .find_first_of(" ") );
                //std::cout << "run: " << program << " --u" << std::endl;
                if( system(( "\"" + program + "\" --update").c_str()) == 0 ) {
                    std::cout
                              << std::endl << " -> Wollen sie ihren Befehl mit der alten Version noch ausführen (oder Programm beenden und neu starten)(Y/n): " << std::flush;

                    std::cin.clear();
                    inp = "";
                    std::getline(std::cin, inp);

                    if(inp == "" || inp == "Y" || inp == "y" || inp == "j" || inp == "J") {
                        return 0;
                    } else
                        exit(0);
                }
            }

        }
    } else if (settings->debugMode)
        std::cout << "Letzte Update Suche vor " << difDays << " tagen!" << std::endl;

    if(settings->debugMode)
        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Exit with success." << std::endl;
    return 0;
}

int ProgramManager::checkLastUpdate(Settings *settings, ssize_t *days = nullptr)
{

    //Wenn die Funktion deaktiviert ist brich ab, wenn nicht nur diffdays verlangt wird
    if(settings->updateWarningDays == 0 && !days) {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": In settings: upDateWaring is deaktivated(seted to 0)." << std::endl;
        return 0;
    }

    std::ifstream ifs(settings->lastUpdateDateFilePath);
    if(!ifs.is_open()) {
        std::ofstream ofs2(settings->lastUpdateDateFilePath);
            if(!ofs2.is_open()) {
                perror(("Konnte die Datei '" + settings->lastUpdateDateFilePath + "' nicht öffnen").c_str());
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": Failed to create Last Update Date File:'" << settings->lastUpdateDateFilePath << "'." << std::endl;
                return 1;
            } else {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": Ordfolgreich LastUpdateTime Save File erstellt:'" << settings->lastUpdateDateFilePath << "'." << std::endl;
                ofs2 << "0" << std::endl;
                ofs2.close();
                ifs.open(settings->lastUpdateDateFilePath);
                if(!ifs.is_open()) {
                    perror(("Konnte die Datei '" + settings->lastUpdateDateFilePath + "' nicht öffnen").c_str());
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Failed to open Last Update Date File:'" << settings->lastUpdateDateFilePath << "'." << std::endl;
                    return 4545;
                }
            }
    }
    std::string line;
    ssize_t difDays = 0;
    if(!std::getline(ifs, line).good()) {
        perror("GetLine from Date failed");
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Get the first Line of the LastUpdateDate File failed." << std::endl;
        return 2;

    } else if( ( ( difDays = static_cast<long long>(pageManager.getDate()) - atoll(line.c_str()) )) >= settings->updateWarningDays) {
        //Gib nachricht nicht aus wenn nur diffday verlangt wird
        if(!days) {
            std::cout << ((settings->colorless) ? "" : "\033[93m") << " => Warnung: SerienListe wurde zuletzt vor " << difDays << " Tagen aktualisiert."
                      << std::endl << "             Mit '" << settings->programName << " search -u' kannst du die Liste aktualisieren." << ((settings->colorless) ? "" : "\033[0m") << std::endl;
        }
    }
    //Wenn keine Ausgabe, sondern nur Tage gespeichgtert werden sollen(days != nullptr), speicher diffdays darin
    if(days)
        *days = difDays;

    if(settings->debugMode)
        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Exit with success." << std::endl;
    return 0;
}

int ProgramManager::defaultModus(Settings *settings)
{

    //Wenn kein Name mit -n Angegeben wurde:
    if(settings->name == "") {
        if(settings->default_checkPath != "") {
            if(settings->default_checkPath.find(settings->pathSymbol) == std::string::npos && settings->default_checkPath.find(settings->wrongPathSymbol) != std::string::npos ) {
                char t = settings->wrongPathSymbol;
                settings->wrongPathSymbol = settings->pathSymbol;
                settings->pathSymbol = t;
            }

            if(settings->default_checkPath[settings->default_checkPath.length()-1] == settings->pathSymbol)
                settings->default_checkPath.pop_back();
            size_t pos = settings->default_checkPath.find_last_of(std::string(1, settings->pathSymbol));

            if( pos != std::string::npos) {
                settings->name = settings->default_checkPath.substr(pos + 1);
                if(settings->debugMode)
                    std::cout << " > Use Path from -C for Name: " << settings->default_checkPath << " -> " << settings->name << std::endl;
            }
        } if(settings->name == "") {
            std::cout << " => Kein Name angegeben." << std::endl;
            std::cout << "Aufruf: " << settings->programName << " default [OPTION]... [NAME]..." << std::endl;
            std::cout << "\"" << settings->programName << " default --help\" liefert weitere Informationen." << std::endl;
            return 0;
        }
    }

    //Überprüfe ob ein Muster existiert:
    if(settings->default_checkPath != "" && settings->default_Searchmuster == "") {
        std::cout << " => Error: [-m]: Kein Muster angegeben." << std::endl;
        return 0;
    }


    //Führe Function aus, die überprüft ob die serie existiert (einmal???)
    auto retVal = pageManager.checkName(settings->pagesInUse, settings->name, settings->useFirstPage, settings->outputFilePaths, settings->default_checkPath);

    if(retVal.status == retVal.FAILED)
        return 67;
    else if(retVal.status == retVal.NOTHING_FOUND || retVal.status == retVal.MULTIPLE_OPTIONS) {
        //Wenn nicht, dann fühe noch eine Suche nach ähnlichen durch && Wenn nur 1ne dacnn frag ob es diese ist.
        int res = 0;
        if( ( res = sucheNach_1_Serien(settings, pageManager, retVal) ) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": sucheNach_1_Serien failed or found more options." << std::endl;
            return (res == -10101) ? 0 : 202;
        }
    } else if( retVal.status == retVal.NO_WORKING_PAGE ) {
        std::cout << " => Error: Keine Funktionierende Internetseite!" << std::endl;
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ":  Keine Funktionierende Internetseite!" << std::endl;
        return 0;
    }

    std::string nameInUrl = retVal.name;
    PAGE page = retVal.pageInUse;
    AccountManager accountManager(settings->accountFilePath, settings->accountNumberPath, page, settings->pagesALL);



    //Liste alle Dateien in dem Ornder von -C auf und speichere diese
    std::string dirFiles;
    if(settings->default_checkPath != "")
        if(listDir(dirFiles, settings->default_checkPath, settings->default_maxDirs, settings->debugMode ) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": listDir failed." << std::endl;
            return 28;
        }
    if(dirFiles.length() > 0)    //Entferne von der liste das \n am ende
        dirFiles.pop_back();



    /* Wenn multihtreading seaktiviert ist, normal login sonst bereite threads vor
    if(settings->maxThreads == 0) {
        // melde bei seriens tream.sx an und speicher cookies.
        if (pageManager.login(accountManager.getNextAccount()) != 0) //----------------------------------------
            return 29;
    }*/

    if(settings->maxThreads > 0) {
        for (unsigned i = 0; i < settings->maxThreads; ++i) {
            if(dirExists(settings->cookieFilePath + "_" + page.url + std::to_string( i ))) {
                std::cout << " => Error: Kann Cokkie-File nicht erstellen: Es existiert bereits ein Ordner mit diesem Namen: \n           '"
                          << settings->cookieFilePath + "_" + page.url + std::to_string( i ) << "'." << std::endl;
                return 174;
            }
            PageManager * pm = new PageManager(settings->proxy_ip + ":" + std::to_string(settings->proxy_port));
            pm->setDebugMode(settings->debugMode);

            //pm->setProxy(settings->proxy_ip, settings->proxy_port);
            //pm->setCookieFile Path(settings->cookieFile Path + std::to_string( i ));

            ThreadData * newThreadData = new ThreadData(i, 0, nameInUrl, -1, settings, &accountManager, pm, page);
            threadList.push_back(newThreadData);
        }
    }

    //Write Name to File if -o is set und kein TXT-FILE angegeben wird
    if(settings->outputFilePaths.size() != 0 && !fileExists( settings->default_checkPath ))
        if(pageManager.writeToFile(settings->outputFilePaths, "Serie: " + settings->name + " (" + nameInUrl + ")" ) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile Function fails when write Name." << std::endl;
            return 31;
        }

    //Finde die anzahl der staffel heraus:
    //download html von der startpage einer serie
    Reply tmp_reply = pageManager.getServerRequest(page.protocol, page.url + page.UrlDir + nameInUrl);
    if(tmp_reply.html == "-1" || tmp_reply.html == "") {
        std::cerr << " => Error: Konnte Seitenquelltext nicht herunterladen." << std::endl;
        return 32;
    }

    //speicher zahl -1, ab da wo /staffel-x nicht mehr vorkommt
    int maxStaffel = pageManager.counterContains(tmp_reply.html, "/staffel-%i");
    if(settings->debugMode)
        std::cout << " > Die Serie " << settings->name << " hat " << maxStaffel << " Staffeln." << std::endl;

    //wenn starterstaffel 0 ist, also letzte staffel, dann ersetzte variable mit maxStaffeln
    if(settings->startSeason == 0)
        settings->startSeason = maxStaffel;

    //For every season
    for (int staffel = settings->startSeason; staffel <= maxStaffel; ++staffel) {
        //Test for stopping Program caused -E, -S
        if(staffel > settings->stopSeason && settings->stopSeason > 0) {
            if(settings->maxThreads != 0)
                if(waitForThreads() != 0) {
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl;
                    return 261;
                }
            if(settings->debugMode)
                std::cout << " > Stoppe, weil Staffel: " << staffel << " > StopStaffel " << settings->stopSeason << std::endl;
            std::cout << " > Fertig, da Staffel " << staffel << " größer ist als StopStaffel " << settings->stopSeason << std::endl;
            return 0;
        }

        //Find out number of all episodes
        if( (tmp_reply = pageManager.getServerRequest(page.protocol, page.url + page.UrlDir + nameInUrl + "/staffel-" + std::to_string(staffel))).html == "-1") {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest failed when download season page." << std::endl;
            return 40;
        }

        int maxFolge = pageManager.counterContains(tmp_reply.html, "/episode-%i");

        //Print seasons
        if(settings->debugMode)
            std::cout << " > Die Staffel " << staffel << " hat " << maxFolge << " Folgen." << std::endl;

        //for every episode
        for (int folge = settings->startEpisode; folge <= maxFolge; ++folge) {

            // stoppe wenn stopfolge größer der folge ist und stopstaffel nicht gesetzt wurde. und stopepisode gröser 0, also aktiv ist
            if(folge > settings->stopEpisode && settings->stopSeason < 1 && settings->stopEpisode > 0) {
                if(settings->maxThreads != 0)
                    if(waitForThreads() != 0) {
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl;
                        return 261;
                    }
                std::cout << " > Fertig, da Folge " << folge << " größer ist als Stopfolge " << settings->stopEpisode << "."<< std::endl;
                return 0;


            // stoppe wenn stopfolge > folge && stopstaffel >= staffel und stopepisode gröser 0, also aktiv ist
            }  else if ( folge > settings->stopEpisode && staffel >= settings->stopSeason && settings->stopEpisode > 0)  {
                if(settings->maxThreads != 0)
                    if(waitForThreads() != 0) {
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl;
                        return 267;
                    }
                std::cout << " > Fertig, da Folge " << folge << " größer ist als Stopfolge " << settings->stopEpisode << std::endl
                          << "   und Staffel " << staffel << " größer gleich Stopstaffel " << settings->stopSeason << " ist." << std::endl;
                return 0;
            }

            //Überprüfe ob, wenn -C vorhanden, die Folge in dem Ordner bereits vorkommt.
            if(settings->default_checkPath != "") {
                if(dirFiles.find(replace( replace( settings->default_Searchmuster, "%Staffel%",  ((staffel < 10) ? "0" : "") + std::to_string(staffel) ),
                                                      "%Folge%",  ((folge < 10) ? "0" : "") + std::to_string(folge) )  ) != std::string::npos) {
                    if(settings->debugMode)
                        std::cout << " > Skippe Folge: S" << staffel << "E" << folge << std::endl;
                    continue;
                }
            }

            //Multihreading Mode
            if(settings->maxThreads > 0) {
                //Wenn nex Thread noch in den Vector passt(weniger Threads als Max), dann Starte neuen mit data aus dem Vector...
                if(nextThread < threadList.size()) {
                    threadList[nextThread]->exitState = 0;
                    threadList[nextThread]->setData(staffel, folge);
                    if(pthread_create(&threadList[nextThread]->thread, nullptr, threadFunction, reinterpret_cast<void*>(threadList[nextThread])) != 0 ) {
                        perror("pthread_creat failed");
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Create thread for redirect converting failed." << std::endl;
                        return 48;
                    }
                    ++nextThread;
                } else { // Sonnst warte bis alle Fertig sind und restarte die Folge
                    if(waitForThreads() != 0) {
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl;
                        return 231;
                    }
                    nextThread=0;
                    folge--;
                    continue;
                }


            // Default Mode
            } else {
                tmp_reply =pageManager.getServerRequest( page.protocol, page.url + page.UrlDir + nameInUrl + "/staffel-" + std::to_string(staffel) + "/episode-" + std::to_string(folge));
                if(tmp_reply.html == "-1") {
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest failed when download episoden page." << std::endl;
                    return 50;
                }
                std::string allLinks = pageManager.getLinks(tmp_reply.html);
                if(settings->genaueHoster == "*," && settings->colorless) {
                    std::cout << settings->colorless << " == colorlessvar" << std::endl;
                    if(settings->debugMode)
                        std::cout << allLinks << std::endl;
                    std::stringstream strstrem(allLinks);
                    std::string line;
                    while (std::getline(strstrem, line).good()) {
                        size_t pos = line.find("/redirect/");
                        if(pos == std::string::npos) {
                            std::cout << " => Error: Konnte den Redirect Link in der Zeile aus LinksListe nicht finden." << std::endl;
                            return 400;
                        } else
                            line.erase(0, pos);
                        line.erase(line.find("\""));
                        if(convertLink(page, line, &accountManager, settings, staffel, folge, allLinks) != 0) {
                            if(settings->debugMode)
                                std::cerr << ">>> Debug In " << __FUNCTION__ << ": convertLink failed." << std::endl;
                            return 51;
                        }
                    }
                    //Stop beacause same episode every account can only 2 videos not 10-12
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Stop Program, because '*'-Hoster is inperformatnt: Every Account can only 2 Vidoes not 10-12." << std::endl;
                    return 0;

                } else {
                    std::string Link = pageManager.chooseHosterLink(allLinks, settings->genaueHoster, settings->languages, settings->debugMode);

                    if(settings->debugMode)
                        std::cout << allLinks << std::endl << ( (Link == "") ? "" : " -> Link: 'https://" + page.url) << Link << ( (Link == "") ? "" : "'\n" );
                    if(convertLink(page, Link, &accountManager, settings, staffel, folge, allLinks) != 0) {
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": convert Link failed." << std::endl;
                        return 51;
                    }
                }


            }
        }
        //Setzte Startepisode zurück für nächste Staffel
        settings->startEpisode = 1;
    }

    if(settings->maxThreads != 0)
        if(waitForThreads() != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl;
            return 292;
        }

    std::cout << " > Fertig" << std::endl;
    return 0;
}

int ProgramManager::directLinkModus(Settings *settings)
{

    if(settings->name == "") {
        std::cout << " => Kein(e) Link(s) angegeben." << std::endl;
        std::cout << "Aufruf: " << settings->programName << " url [OPTION]... [URL]..." << std::endl;
        std::cout << "\"" << settings->programName << " url --help\" liefert weitere Informationen." << std::endl;
        return 0;
    }

    std::istringstream iStrStream( replace( settings->name, ",", "\n" ) + "\n" );
    std::string line;

    //if(pageManager.login(accountManager.getNextAccount()) != 0)
    //    return 71;

    while (getline(iStrStream, line).good()) {
        //extrahiere redirekt und page
        std::string redL;
        PAGE page;
        if(line == "")
            continue;

        else if(line.find("/redirect/") == std::string::npos) {
            std::cout << " => Error: Invalid Redirect Link: '" << line << "'" << std::endl;
            continue;

        }  else if(line.find("://") == std::string::npos) {
            if(settings->direktLink_explizitPage.url == "") {
                std::cout << " => Kann '://' bei '" << line << "' die Internetseite nicht finden: Benutze -s [url], --standart-page [url]," << std::endl
                          << "    um /redirect/xyz Links für die Internetseite <url> (z.B. anicloud.io) umzuwandel.n" << std::endl;
                continue;
            }
            redL = line.erase(0, line.find("/redirect/"));
            page = settings->direktLink_explizitPage;


        } else {
            line.erase(0, line.find("://") + 3); // remove http(s)://
            std::string url = line.substr(0, line.find("/redirect/"));
            bool found = false;
            for( const auto &p : settings->pagesInUse ) {
                if(p.url == url) {
                    found = true;
                    page = p;
                    break;
                }
            }
            if( !found ) {
                std::cout << " => Error: Unbekannte Seite: '" << url << "'" << std::endl;
                continue;
            }
            redL = line.erase(0, line.find("/redirect/"));
        }

        AccountManager accountManager(settings->accountFilePath, settings->accountNumberPath, page, settings->pagesALL);

        //remove all behind "
        if(redL.find("\"") != std::string::npos)
            redL.erase(redL.find("\""));

        if(convertLink(page, redL, &accountManager, settings) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": convert Link failed." << std::endl;
            return 78;

         }
    }
    if(settings->debugMode)
        std::cerr << ">>> Debug In " << __FUNCTION__ << ": Success." << std::endl;
    return 0;
}

int ProgramManager::searchModus(Settings *settings, std::string *saveTo, bool noPrint)
{
    ssize_t dayddiff;
    if(settings->showLastUpdate) {
        if(checkLastUpdate(settings, &dayddiff) != 0) {
            std::cout << " => Error: CheckLasUpdate-Funktion gab einen Error zurück." << std::endl;
            return -1;
        } else
            std::cout << " => Letzte Aktualisierung: Vor " << dayddiff << " Tagen." << std::endl;
        if(!settings->search_wantUpdate && settings->name == "") {
            if(settings->debugMode)
                std::cout << " >>> Debug: Verlasse Funktion searchModus: Nur -l" << std::endl;
            return 0;
        }

    } if(settings->search_wantUpdate) {
        int res = searchModus_update(settings) ;
        if(res == 0) {
            std::cout << "Erfolgreich geupdatet: Die Serienliste ist nun auf dem neusten Stand." << std::endl;
            if (settings->name == "") {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": Stop after Update: No Name => Only Updating." << std::endl;
                return 0;
            }

        } else {
            std::cout << " => Error: Das updaten der Serienliste ist fehlgeschlagen." << std::endl;
            return res;
        }

    } else if(settings->name == "") {
        std::cout << " => Kein Name angegeben." << std::endl;
        std::cout << "Aufruf: " << settings->programName << " search [OPTION]... [NAME]..." << std::endl;
        std::cout << "\"" << settings->programName << " search --help\" liefert weitere Informationen." << std::endl;
        return 0;
    } else if(settings->name.find('|') != std::string::npos) {
        std::cout << " => Error: Fehlerhaftes Zeichen \"|\" im Namen!" << std::endl;
        return 0;
    }

    //Check for last Update.. (glaub hier nocghmal die funktion, um datei zu erstellen, auch wenn ausgabe deaktiviert is, kann aber auch sein dass der teil ghier weg gehört)
    if(checkLastUpdate(settings) != 0) {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": checkLastUpdate function failed." << std::endl;
        return -1;
    }


    std::ifstream ifs(settings->serienListPath);
    if(!ifs.is_open()) {
        std::cout << " => Keine SerienListe vorhanden. Erstelle eine neue..." << std::endl;
        if(searchModus_update(settings) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": searchModus_update function failed." << std::endl;
            return 354;
        }
        else {
            ifs.open(settings->serienListPath);
            if(!ifs.is_open()) {
                perror(" => Error: Couldn't open SerienList file after update again.");
                return 434;
            }
            std::cout << "Erfolgreich gedownloadet." << std::endl;
        }
    }


    //Save file in string:
    std::string serienListe = std::string((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

    //Suche alle Möglichkeiten
    std::string fullList = pageManager.grep(serienListe, settings->name, settings->search_IgnoreUpperLower);
    serienListe.clear(); // Speicher freigeben

    /*//Text mit Farben versehen
    if(!settings->colorless) {
        for (size_t pos = pageManager.upper_string( finds ).find( pageManager.upper_string( settings->name ), 0);
                pos != std::string::npos;
                pos =  pageManager.upper_string( finds ).find( pageManager.upper_string( settings->name ), pos + settings->name.length() + strlen("\033[37m\033[0m")))
            finds.insert(pos, ( (finds.find(settings->name, pos) == pos) ? "\033[32m" : "\033[36m" ) ).insert(pos + settings->name.length() + strlen("\033[37m"), "\033[0m");
    }*/

    std::string finds;

    //------------------------------------------------> Extrahiere alle Zeilen raus, die aus den Aktivierten Seiten sind
    std::istringstream ifS(fullList + "\n");
    std::string l, allUrlsInUSe, allPages;
    for( const auto &p : settings->pagesInUse )
        allUrlsInUSe += ((allUrlsInUSe == "") ? "" : ",") + p.url;
    for( const auto &p : settings->pagesALL )
        allPages += ((allPages == "") ? "" : ",") + p.url;

    while (std::getline(ifS, l)) {
        if( l.find_last_of('|') == std::string::npos ) {
                continue;
        } else if( allUrlsInUSe.find( l.substr(l.find_last_of('|') + 1) ) != std::string::npos ) {
            finds += l + "\n";
        } else if ( allPages.find( l.substr(l.find_last_of('|') + 1) ) == std::string::npos  ) {
            std::cout << settings->setPColor(Settings::Brown_Orange) << " => WARNUNG: In der Serienliste befindet sich ein ungültiger Eintrag: Unbekannte Seite: " << l.substr(l.find_last_of('|') + 1) <<
                         "\n    Verwenden sie '" << settings->programName << "' s -u, search --update um die Liste zu aktualisieren!" << settings->resetPColor() << std::endl;
            continue;
        }
    } if(finds.size() >= 1)
        finds.pop_back();
    //-------------------------------------------

    if(settings->debugMode)
        std::cout << "  <DEBUG> FiNDS: '" << finds << "'" << std::endl;

    if(saveTo) {
        //Save List to Variable if set
        *saveTo=finds;
    } if (noPrint) {
        return 0;
    }

    //Text mit Farben versehen
    if(!settings->colorless) {
        std::string UpperFinds = pageManager.upper_string( finds );
        std::string UpperName = pageManager.upper_string( settings->name );
        for (size_t pos = UpperFinds.find( UpperName, 0); pos != std::string::npos; pos =  UpperFinds.find( UpperName, pos + settings->name.length() + strlen("\033[37m\033[0m"))) {
            bool exaktGeschrieben = (finds.find(settings->name, pos) == pos);
            finds.insert(pos, ( (exaktGeschrieben) ? "\033[32m" : "\033[36m" ) ).insert(pos + settings->name.length() + strlen("\033[37m"), "\033[0m");
            UpperFinds.insert(pos, ( (exaktGeschrieben ) ? "\033[32m" : "\033[36m" ) ).insert(pos + settings->name.length() + strlen("\033[37m"), "\033[0m");
        }
    }
    //Ausgabe
    if(finds == "") {
        std::cout << " => Für '" << settings->name << "' wurde(n) keine Serie(n) gefunden." << std::endl;
        return 0;
    }
    std::stringstream strstream(finds);
    std::string line;
    std::cout << " => Für '" << settings->name << "' wurde(n) folgende Serie(n) gefunden: " << std::endl;

    std::string lastPageUrl;
    while (getline(strstream, line)) {

        //splitting
        ///Nadia The Secret, Fushigi no Nadia|/nadia-zauberstein|Nadia und Zauberstein|seriento
       // into Vector

        std::vector<std::string> parts;
        std::istringstream f(line + "|");
        std::string p;
        while (getline(f, p, '|').good())
                parts.push_back(p);
        if(parts.size() != 4) {
            std::cout << " => Error: Invalid SerienListeEintrag: '" << line << "'" << parts.size() << std::endl;
            continue;
        }

        if( lastPageUrl != parts.at(3) ) {
            std::cout <<  ((settings->colorless) ? "" : "\033[93m") << "Auf '" << parts.at(3) << "'..." << ((settings->colorless) ? "" : "\033[0m") << std::endl;
            lastPageUrl =  parts.at(3);
        }

        std::cout << "  > " << parts.at(2) << "\t[" << parts.at(1).erase(0, 1) << "]"
                  << ( ( !settings->search_show_othernames || line[0] == '|') ? "" : "\t( " + parts.at(0) + " )" ) << std::endl;
        //zähne hoch!!

        ///That Time I Got Reincarnated as a Slime|/tensei-shitara-slime-datta-ken|Tensei Shitara Slime Datta Ken|ANIME
    } /// >  Tensei Shitara Slime Datta Ken      [tensei-shitara-slime-datta-ken]        ( That Time I Got Reincarnated as a Slime ) <s.to>



    if(settings->debugMode)
        std::cerr << ">>> Debug In " << __FUNCTION__ << ": success." << std::endl;
    return 0;
}

int ProgramManager::infoModus(Settings *settings)
{
    if(settings->name == "") {
        std::cout << " => Kein Name angegeben." << std::endl;
        std::cout << "Aufruf: " << settings->programName << " info [OPTION]... [NAME]..." << std::endl;
        std::cout << "\"" << settings->programName << " info --help\" liefert weitere Informationen." << std::endl;
        return 0;
    }

    //Führe Function aus, die überprüft ob die serie existiert
    auto retV = pageManager.checkName(settings->pagesInUse, settings->name, settings->useFirstPage, settings->outputFilePaths, settings->default_checkPath );
    if(retV.status == retV.FAILED)
        return 145;
    else if(retV.status == retV.NOTHING_FOUND || retV.status == retV.MULTIPLE_OPTIONS ) {
        //Wenn nicht, dann fühe noch eine Suche nach ähnlichen durch.
        int res = 0;
        if( ( res = sucheNach_1_Serien(settings, pageManager, retV) ) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": sucheNach_1_Serien function failed." << std::endl;
            return (res == -10101) ? 0 : 28;
        }
    } else if( retV.status == retV.NO_WORKING_PAGE ) {
        std::cout << " => Error: Keine Funktionierende Internetseite!" << std::endl;
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ":  Keine Funktionierende Internetseite!" << std::endl;
        return 0;
    }
    std::string nameInUrl = retV.name;
    PAGE page = retV.pageInUse;

//    std::cout << "Serie: " + settings->name + " (" + nameInUrl + ")" << std::endl;

    //write Name to file
    if( !settings->no_log && pageManager.writeToFile(settings->outputFilePaths, "\n\nSerie: " + settings->name + " (" + nameInUrl + ")") != 0)
    {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
        return 100;
    }


    //Finde Anzahl der Staffel heraus:
    Reply tmp_reply = pageManager.getServerRequest(page.protocol, page.url + page.UrlDir + nameInUrl);
    if(tmp_reply.html == "-1") {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed: at homepage." << std::endl;
        return 32;
    }

    std::string green = ((settings->colorless) ? "" : "\033[92m"),
                lila = ((settings->colorless) ? "" : "\033[95m"),
                Lightyellow = ((settings->colorless) ? "" : "\033[93m"),
                Darkyellow = ((settings->colorless) ? "" : "\033[33m"),
                blue = ((settings->colorless) ? "" : "\033[96m"),
                white = ((settings->colorless) ? "" : "\033[0m");


    if( ! settings->skipEpisodenNameOutput) {

        //Für FolgenNummer ingesmammt
        int gesammtFolge = 0;
        //speicher (zahl -1), ab da wo /staffel-x nicht mehr vorkommt
        int maxStaffel = pageManager.counterContains(tmp_reply.html, "/staffel-%i");

        //Um namen der Folge für jede Staffel zu bekommen
        for (int staffel = 1; staffel <= maxStaffel; ++staffel) {
            Reply tmpReply = pageManager.getServerRequest(page.protocol, page.url + page.UrlDir + nameInUrl + "/staffel-" + std::to_string(staffel));
            if(tmpReply.html == "-1") {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed: at season page." << std::endl;
                return 40;
            }

            int folgen = pageManager.counterContains(tmpReply.html, "/episode-%i");
            std::cout << std::endl
                      << green << "Die Staffel " << staffel << " hat " << folgen << " Folge" << ((folgen > 1) ? "n" : "") << "." << white << std::endl
                      << std::endl;
            if(!settings->no_log && pageManager.writeToFile(settings->outputFilePaths, "\nDie Staffel " + std::to_string(staffel)
                                       + " hat " + std::to_string(folgen) + " Folge" + ((folgen > 1) ? "n" : "") + ".\n") != 0)
            {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                return 110;
            }


            std::string html = tmpReply.html;
            size_t pos = 0;
            if( (pos = html.find("<tr ")) == std::string::npos) {
                std::cout << " => Error: Konnte Position von '<tr ' nicht finden." << std::endl;
                return 41;
            } else
                html.erase(0, pos);
            if( (pos = html.find("</tbody>")) == std::string::npos) {
                std::cout << " => Error: Konnte Position von '</tbody>' nicht finden." << std::endl;
                return 42;
            } else
                html.erase(pos, std::string::npos);

            html = replace(html, "\n", "");
            html = replace(html, "</tr>", "\n");

            std::stringstream folgenListe(html);
            std::string line;

            while (std::getline(folgenListe, line).good()) {
                std::string titel;
                gesammtFolge = gesammtFolge + 1;

                if( (pos = line.find("\"> Folge")) == std::string::npos) {
                    std::cout << " => Error: Konnte Position von '\"> Folge' nicht finden." << std::endl;
                    return 43;
                } else
                    line.erase(0, pos + 9);
                if( (pos = line.find(" </a>")) == std::string::npos) {
                    std::cout << " => Error: Konnte Position von ' </a>' nicht finden." << std::endl;
                    return 44;
                }
                std::cout << lila << "Ep. " << blue << ( (gesammtFolge < 100) ? ( (gesammtFolge < 10) ? "00" : "0" ) : "" ) << gesammtFolge << lila
                          << " ( " << blue << "S" << ( (staffel < 10) ? "0" : "" ) << staffel
                          << "E" << ( ( atoi( line.substr(0, pos).c_str() ) < 10) ? "0" : "" ) << line.substr(0, pos) << lila << " ):" << white <<std::endl;

                if(!settings->no_log && pageManager.writeToFile(settings->outputFilePaths, "Ep. " + std::string( (gesammtFolge < 100) ? ( (gesammtFolge < 10) ? "00" : "0" ) : "" )
                                           + std::to_string(gesammtFolge) + " ( S" + ( (staffel < 10) ? "0" : "" ) + std::to_string(staffel) + "E"
                                           + ( ( atoi( line.substr(0, pos).c_str() ) < 10) ? "0" : "" ) + line.substr(0, pos) + " ):" ) != 0) {
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                    return 105;
                }

                if( (pos = line.find("<strong>")) == std::string::npos) {
                    std::cout << " => Error: Konnte Position von '<strong>' nicht finden." << std::endl;
                    return 43;
                } else
                    line.erase(0, pos + 8);
                if( (pos = line.find("</strong>")) == std::string::npos) {
                    std::cout << " => Error: Konnte Position von '</strong>' nicht finden." << std::endl;
                    return 44;
                }
                titel = line.substr(0, pos);
                if(titel != "") {
                    std::cout << lila << "  > Titel 1: " << Lightyellow << titel << white << std::endl;
                    if(!settings->no_log && pageManager.writeToFile(settings->outputFilePaths, "  > Titel 1: " + titel) != 0) {
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                        return 110;
                    }
                }

                if( (pos = line.find("<span>")) == std::string::npos) {
                    std::cout << " => Error: Konnte Position von '<span>' nicht finden." << std::endl;
                    return 43;
                } else
                    line.erase(0, pos + 6);
                if( (pos = line.find("</span>")) == std::string::npos) {
                    std::cout << " => Error: Konnte Position von '</span>' nicht finden." << std::endl;
                    return 44;
                }
                titel = line.substr(0, pos);
                if(titel != "") {
                    std::cout << lila << "  > Titel 2: " << Darkyellow << titel << white << std::endl;
                    if(!settings->no_log && pageManager.writeToFile(settings->outputFilePaths, "  > Titel 2: " + titel) != 0) {
                        if(settings->debugMode)
                            std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                        return 120;
                    }

                }
            }

        }

    }

    //Datum & FSK
    std::string line = pageManager.grep(tmp_reply.html, "<small> (<span itemprop=\"startDate\"><a");
    if(line == "") {
        std::cout << " => Error: Konnte '<small> (<span itemprop=\"startDate\"><a' nicht finden." << std::endl;
        return 83;
    }

    std::string startStopDates[2];
    size_t pos = 0, pos2 = 0;

    //Date
    for (int i = 0; i < 2; ++i) {
        if( (pos = line.find("href=")) == std::string::npos ) {
            std::cout << " => Error: Konnte 'href=' nicht finden." << std::endl;
            return 84;
        } else
            line.erase(0, pos + 5);

        if( (pos = line.find(">")) == std::string::npos ) {
            std::cout << " => Error: Konnte '>' nicht finden." << std::endl;
            return 85;
        } else if ((pos2 = line.find("</a>")) == std::string::npos ) {
            std::cout << " => Error: Konnte '</a>' nicht finden." << std::endl;
            return 86;
        }
        startStopDates[i] = line.substr(pos + 1, pos2 - pos -1);
    }

    //FSK
    if( (pos = line.find("data-fsk=\"")) == std::string::npos ) {
        std::cout << " => Error: Konnte 'data-fsk=\"' nicht finden." << std::endl;
        return 87;
    } else if ((pos2 = line.find("\" class=\"fsk")) == std::string::npos ) {
        std::cout << " => Error: Konnte '\" class=\"fsk' nicht finden." << std::endl;
        return 86;
    }
    std::string fsk = line.substr(pos + 10, pos2 -pos - 10);

    //Deskription
    if( (pos = tmp_reply.html.find("data-full-description=")) == std::string::npos) {
        std::cout << " => Error: Konnte 'data-full-description=' nicht finden." << std::endl;
        return 83;
    } else if ((pos2 = tmp_reply.html.find("\">", pos)) == std::string::npos ) {
        std::cout << " => Error: Konnte '\">' nicht finden." << std::endl;
        return 86;
    }
    std::string description = replace( replace( tmp_reply.html.substr(pos + 23, pos2 - pos - 23), "\n", "" ), "<br />", "" );

    //remove bug text:
    description = replace(description, "&amp;quot;", "\""); //

    description = replace(description, "&amp;", "&"); //
    description = replace(description, "&lt;", "<"); //
    description = replace(description, "&gt;", ">"); //

    description = replace(description, "<br />", " "); //
    description = replace(description, "&quot;", "\""); //
    description = replace(description, "&apos;", "'"); //


    //Genres
    std::vector<std::string> genres;
    line = pageManager.grep(tmp_reply.html, "\"genre\">");
    if(line == "") {
        std::cout << " => Error: Konnte '\"genre\">' nicht finden." << std::endl;
        return 87;
    }
    for (pos = line.find("\"genre\">"); pos != std::string::npos; pos = line.find("\"genre\">", pos + 7)) {
        if( (pos2 = line.find("</a>", pos)) == std::string::npos) {
            std::cout << " => Error: Konnte '</a>' nicht finden." << std::endl;
            return 89;
        }
        genres.push_back(line.substr(pos + 8, pos2 - pos - 8));
    }

    //CoverLink
    line = pageManager.grep(tmp_reply.html, "title=\"Cover");
    if( (pos = line.find("data-src=\"")) == std::string::npos) {
        std::cout << " => Error: Konnte 'data-src=\"' nicht finden." << std::endl;
        return 90;
    } else if ((pos2 = line.find("\"", pos + 10)) == std::string::npos ) {
        std::cout << " => Error: Konnte '\"' nicht finden." << std::endl;
        return 86;
    }
    std::string coverLink = line.substr(pos + 10, pos2 - pos -10);


    //Ausgabe

    std::cout << lila << "\nProduktion von " << blue << startStopDates[0] << lila << " bis " << blue << startStopDates[1] << lila << std::endl
              << "FSK: " << blue << fsk << lila << std::endl
              << "Cover Bild: " << green << coverLink << lila << std::endl
              << "Genre(s): " << blue << std::flush;
    for( const auto &e : genres)
        std::cout << e << " ";

    std::cout << lila << std::endl << "\nBeschreibung: " << green << description << white << std::endl;


    //Schreibe das auch in ein Text file:
    std::string all_genres;
    for( const auto &e : genres)
        all_genres += e + " ";

    if(!settings->no_log && pageManager.writeToFile(settings->outputFilePaths, "\nProduktion von " + startStopDates[0] + " bis " + startStopDates[1] + "\n"
                                                         "FSK: " + fsk + "\n" + "Cover Bild: " + coverLink + "\n"  + "Genre(s): " + all_genres + "\n"
                                                         "\nBeschreibung: " + description + "\n") != 0)
    {
        if(settings->debugMode)
            std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
        return 130;
    }

    //DOWNLOADE DATEI....
    if(settings->downloadCoverPfad != "") {
        if( pageManager.downLoadToFile(  settings->downloadCoverPfad, ((coverLink.find("http") == std::string::npos) ? (page.protocol + page.url) : "") + coverLink ) != 0) {
            std::cout << " => Error: Konnte Bild nicht herunterladen." << std::endl;
            return 89;
        }
    }

    if(settings->debugMode)
        std::cerr << ">>> Debug In " << __FUNCTION__ << ": success exit." << std::endl;
    return 0;
}

int ProgramManager::newsModus(Settings *settings)
{
    if(settings->pagesInUse.size() < 1) {
        std::cout << " => Error Keine Internet Seiten vorhanden." << std::endl;
        return -12;
    }

    for( const auto &page : settings->pagesInUse ) {
        std::cout <<  ((settings->colorless) ? "" : "\033[93m") << "Auf '" << page.url << "'..." << ((settings->colorless) ? "" : "\033[0m") << std::endl;

        size_t pos = 0;
        std::string html = pageManager.getServerRequest(page.protocol, page.url +"/neue-episoden").html;
        if(html == "-1") {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed." << std::endl;
            return 1;
        }

        if( (pos = html.find("<div class=\"row\">")) == std::string::npos ) {
            std::cout << " => Error: Konnte Position von '<div class=\"row\">'' nicht finden" <<std::endl;
            return 2;
        } else
            html.erase(0, pos + 17);
        if( (pos = html.find("<div class=\"cf\"></div>")) == std::string::npos ) {
            std::cout << " => Error: Konnte Position von '<div class=\"cf\"></div>' nicht finden" <<std::endl;
            return 2;
        } else
            html.erase(pos + 12);

        html = replace(html, "\n", "");
        html = replace(html, "class=\"row\"", "\n");

        std::stringstream strstream(html + "\n");
        html.clear();
        std::string line;
        while (std::getline(strstream, line).good()) {

            size_t pos = line.find("<strong>");
            size_t pos2 = line.find("</strong>");
            if(pos == std::string::npos) {
                std::cout << " => Error: Konnte Position von '<strong>' nicht finden" <<std::endl;
                return 3;
            } else if(pos2 == std::string::npos) {
                std::cout << " => Error: Konnte Position von '</strong>' nicht finden" <<std::endl;
                return 4;
            }
            std::string name = line.substr(pos + 8, pos2 - pos - 8);

            if( (pos = line.find("blue2\">")) == std::string::npos) {
                std::cout << " => Error: Konnte Position von 'blue2\">' nicht finden" <<std::endl;
                return 5;
            } else if( (pos2 = line.find("</span>", pos)) == std::string::npos) {
                std::cout << " => Error: Konnte Position von '' nicht finden" <<std::endl;
                return 6;
            }
            std::string id = replace( line.substr(pos + 7, pos2 - pos - 7), " ", "");

            if( (pos = line.find("Right\">")) == std::string::npos) {
                std::cout << " => Error: Konnte Position von 'Right\">' nicht finden" <<std::endl;
                return 5;
            } else if( (pos2 = line.find("</span>", pos)) == std::string::npos) {
                std::cout << " => Error: Konnte Position von '</span>' nicht finden" <<std::endl;
                return 6;
            }
            std::string date = line.substr(pos + 7, pos2 - pos - 7);

            std::cout << " > " << ((settings->colorless) ? "" : "\033[97m") << date << ((settings->colorless) ? "" : "\033[0m") << ": "
                      << ((settings->colorless) ? "" : "\033[96m") << name << ((settings->colorless) ? "" : "\033[0m") << ": "
                      << ((settings->colorless) ? "" : "\033[92m") << id << ((settings->colorless) ? "" : "\033[0m") << std::endl;
        }


        if(settings->useFirstPage)
            break;
        else
            std::cout << std::endl;

    }

    return 0;
}

int ProgramManager::updateModus(Settings *settings)
{
    if(settings->VersionFileName == "" || settings->ProgrammFileName == "") {
        std::cout << " => Error: Kein Download Link verfügbar!" << std::endl;
        return 4;
    }

    std::cout << " => INFO: Suche nach der neusten Version..." << std::endl;
    std::string html = pageManager.getServerRequest("", UpdaterCloudUrlWithPath + settings->VersionFileName).html;
    if( html == "-1" || html == "" || html.find("\n") == std::string::npos) {
        std::cerr << (" => Warnung: Verwende 2t-Link für Download!") << std::endl;
        html = pageManager.getServerRequest( "", SecondUpdaterCloudUrlWithPath + settings->VersionFileName).html;
    }


    if( html == "-1" || html == "" || html.find("\n") == std::string::npos) {
        // Wenn debug mode print error
        if(settings->debugMode)
            std::cerr << " => Error: Download newst Version failed." << std::endl;
         // no error output in pagemanager => print error
        else if(html == "")
            std::cout << " => Error: Das herunterladen der neusten Version ist fehlgeschlagen." << std::endl;
        return 1;
    } else {
        html = replace(html, "\r", "");
    }


    // Get newst Version
    std::string neusteVersion = html.substr(0, html.find("\n"));
    html.erase(0, html.find("\n") + 1);

    //Überprüfe onb neue Version einen . enthält
    if(neusteVersion.find(".") == std::string::npos) {
        size_t pos;
        if((pos = html.find("h1>")) != std::string::npos)
            std::cout << " => Das herunterladen ist fehlgeschlagen: '" << html.substr(pos + 3, html.find("</h1>") - pos -3) << "'." << std::endl;
        else
            std::cout << " => Error: Die neuste Version ist ungültig: '" << neusteVersion << "'." << std::endl;
        return -3;
    }

    //Gib Versionenunterschie aus
    std::cout << " => INFO: Jetzige Version: '" << settings->version << "' - Neueste Version: '" << neusteVersion << "'" << std::endl;

    //Print INFOs
    std::cout << "\n => Infos (zur Version): " << std::endl;
    std::string line;
    std::stringstream strstream(html+ "\n");
    while (std::getline(strstream, line).good()) {
        if(line != "")
            std::cout << ((settings->colorless) ? ("") : "\033[92m  > ") << line << ((settings->colorless) ? ("") : "\033[0m") << std::endl;
    }

    //Vergleiche Versionen:
    switch (pageManager.compareVersions(settings->version, neusteVersion)) {
    case 0: {
        std::cout << "\n => Du benützt bereits die neuste Release-Version." << std::endl;

        //Speicher Datum des Updates...
        std::ofstream ofs;
        ofs.open(settings->lastProgrammUpdateDateFilePath, std::ios::trunc);
        if(!ofs.is_open()) {
            perror("Konnte UpdateDate-Datei nicht öffnen");
            return 113;
        } else {
            //Schreibe Liste in das TextFile
            ofs << pageManager.getDate() << std::endl;
            ofs.close();
        }

        return 0;
    } case 1:
        //Diese Version ist klleienr als aktuelle Version => Updatete
        break;
    case 2: {
        std::cout << "\n => Du benützt bereits eine Aktuellere Version als die neuste Release-Version." << std::endl;

        //Speicher Datum des Updates...
        std::ofstream ofs;
        ofs.open(settings->lastProgrammUpdateDateFilePath, std::ios::trunc);
        if(!ofs.is_open()) {
            perror("Konnte UpdateDate-Datei nicht öffnen");
            return 113;
        } else {
            //Schreibe Liste in das TextFile
            ofs << pageManager.getDate() << std::endl;
            ofs.close();
        }

        return 0;
    } default:
        //Error
        return 2;
    }

    //lege pfad zum speichern fest
    std::string downloadedFilePath = settings->cacheDir + "NeusteVersion" + ((settings->pathSymbol == '\\') ? ".exe" : "");

    //wenn dort schon eine datei existiert, lösche diese
    std::cout << "\n => INFO: Bereinige Downloadpfad, falls alte Dateien vorhanden sind..." << std::endl;
    if(fileExists(downloadedFilePath)) {
        if(remove(downloadedFilePath.c_str()) != 0 || fileExists(downloadedFilePath) ) {
            perror((" => Error: Das löschen der Datei '" + downloadedFilePath + "' ist fehlgeschlagen").c_str());
            return 13;
        } else if (settings->debugMode) {
            std::cout << " => DEBUG: Erfolgreich alte gedownloadete Datei '" << downloadedFilePath << "' gelöscht." << std::endl;
        }
    }

    //Download new Version of Program
    std::cout << " => INFO: Lade neue Version herunter..." << std::endl;

    if( pageManager.downLoadToFile(downloadedFilePath, UpdaterCloudUrlWithPath + settings->ProgrammFileName) != 0) {
        std::cerr << (" => Warnung: Verwende 2t-Link für Download!") << std::endl;

        if( pageManager.downLoadToFile(downloadedFilePath, SecondUpdaterCloudUrlWithPath + settings->ProgrammFileName) != 0) {
            std::cout << "\n => Error: Das herunterladen der neuen Version ist fehlgeschlagen." << std::endl;
            return 3;
        }
    } std::cout << std::endl;


    //Make ist executable for test execution
#ifdef __linux__
    std::cout << " => INFO: Mache das Programm ausführbar..." << std::endl;
    if(chmod(downloadedFilePath.c_str(), S_IRWXU) != 0) {
        perror(" => Error: Chmod failed");
        return 4;
    }

    //Führe neue Version aus und überprüfe rückgabewert
    std::cout << " => INFO: Überprüfe die Funktionalität der neuen Version(" << downloadedFilePath << ")...\n" << std::endl;

    if( system((downloadedFilePath + " --version" ).c_str()) != 0) {
        std::cerr << (" => Error: Ausführen der neuen Version ist fehlgeschlagen") << std::endl;
        return 5;
    }


#endif



    //find exePath heraus
    std::string exePath = pageManager.getExePath();
    if(exePath == "") {
        std::cout << " => Error: Function getExepath() ist fehlgeschlagen." << std::endl;
        return 6;
    }

    //lege pfad für alte version fest
    std::string oldVersionPah = settings->cacheDir + "oldVersion" + ((settings->pathSymbol == '\\') ? ".exe" : "");

    //lösche falls vorhanden altes backup
    std::cout << "\n => INFO: Lösche alte Nofall Version falls vorhanden..." << std::endl;
    if(fileExists(oldVersionPah)) {
        if(remove( oldVersionPah.c_str() ) != 0 || fileExists(oldVersionPah)) {
            perror((" => Error: Das löschen der Datei '" + oldVersionPah + "' ist fehlgeschlagen.").c_str());
            return 14;
        } else if (settings->debugMode) {
            std::cout << " => DEBUG: Erfolgreich Notfall Version '" << oldVersionPah << "' gelöscht." << std::endl;
        }
    }

    //verschiebe neue jetzige version zu backup
    std::cout << ((settings->colorless) ? ("") : "\033[92m") <<  " => INFO: Verschiebe alte Version für Notfälle zu: '" << oldVersionPah << "'." << ((settings->colorless) ? ("") : "\033[0m")  << std::endl;

    if(rename(exePath.c_str(), oldVersionPah.c_str() ) != 0) {
        perror((" => Error das Verschieben von '" + exePath + "' -> '" + oldVersionPah + "' ist fehlgeschlagen").c_str());
        return 7;
    }

    if( fileExists(exePath) && fileExists(oldVersionPah) ) {
        std::cout << ((settings->colorless) ? ("\n") : "\n\033[33m")
                  <<  "!! => WARNUNG: --->Die Aktuelle Version konnte nicht verschoben, sondern nur kopiert werden! ( Z.: Operation Laufwerksübergreifend ? )\n"
                  <<  "   ==> Aktuelle Version umbenennen. (Die Datei kann danach gelöscht werden!) " << ((settings->colorless) ? ("") : "\033[0m")   << std::endl;
        if(fileExists(exePath + "_ALT")) {
            std::cout <<  ((settings->colorless) ? ("") : "\033[33m")  << " => WARNUNG: Es existiert bereits eine Datei mit dem Namen "
                        << exePath + "_ALT" <<  ((settings->colorless) ? ("") : "\033[0m") << "\n"   << "Diese Datei loeschen: (Nur Enter um fortzufahren): " << std::flush;

            std::string inp;
            std::getline(std::cin, inp);
            std::cout << std::endl;

            if( inp != "" ) {
                std::cout << "Abbruch..." << std::endl;
                return 0;
            }

            if(remove( (exePath + "_ALT" ).c_str() ) != 0 || fileExists(exePath + "_ALT") ) {
                perror((" => Error: Das löschen der Datei '" + exePath + "_ALT" + "' ist fehlgeschlagen.").c_str());
                return 1144;
            }

        }

        if( rename(exePath.c_str(), (exePath + "_ALT").c_str() ) != 0 || fileExists(exePath) ) {
            perror(" => ERROR: Umbennen auch fehlgeschlagen");
            return 2314;
        } else {
            std::cout << "      -> Umbenennen erfolgreich. Fahre fort..." << std::endl;
        }
    }

    if(fileExists(exePath)) {
        std::cout << " => WARNUNG: Aktuelle Version existiert nach dem Verschieben immer noch!" << std::endl;
        if(remove( exePath.c_str() ) != 0 || fileExists(exePath) ) {
            perror((" => Error: Das löschen der aktuellen Version '" + exePath + "' ist fehlgeschlagen.").c_str());
            return 114;
        }
    }


    //verschibe neue Version
    std::cout << " => INFO: Ersetzte alte Version mit neuer Version des Programms..." << std::endl;

    if(rename(downloadedFilePath.c_str(), exePath.c_str() ) != 0) {
        perror((" => Error: Das Verschieben von '" + downloadedFilePath + "' nach '" + exePath + "' ist fehlgeschlagen").c_str());

        return 7;
    } else {
        std::cout << " => INFO: Erfolgreich verschoben und ersetzt:\n          '"
                  << downloadedFilePath << "' -> '" << exePath << "'" << std::endl;
    }

    if(fileExists(downloadedFilePath)) {
        std::cout << " => WARNUNG: Download-Datei existiert nach dem Verschieben immer noch! Ist diese Operation vielleicht Laufwerksübergreifend? ( Falls ja, starten sie "
                    << settings->programName << " ggf. von ihrem C:\\-Laufwerk." << std::endl;

        if(remove( downloadedFilePath.c_str() ) != 0 || fileExists(downloadedFilePath) ) {
            perror((" => Error: Das löschen der Downloaddatei '" + downloadedFilePath + "' ist fehlgeschlagen.").c_str());
            return 118;
        }
    }

    std::cout << ((settings->colorless) ? ("") : "\033[92m") << "\n => Update Erfolgreich ausgeführt: '" << settings->version <<
                 "' -> '" << neusteVersion << "'" << ((settings->colorless) ? ("") : "\033[0m") << std::endl;

    //Speicher Datum des Updates...
    std::ofstream ofs;
    ofs.open(settings->lastProgrammUpdateDateFilePath, std::ios::trunc);
    if(!ofs.is_open()) {
        perror("Konnte UpdateDate-Datei nicht öffnen");
        return 113;
    } else {
        //Schreibe Liste in das TextFile
        ofs << pageManager.getDate() << std::endl;
        ofs.close();
    }

    return 0;
}

int ProgramManager::cleanUpSettingsAndCache(Settings *settings)
{
    //Alle Groß
    settings->name = pageManager.upper_string(settings->name);

    //setting dir
    if(settings->name == "SETTINGS" || settings->name == "ALL") {
        if( ! removeDirIsOk(settings->configDir, settings, settings->askForEveryDir)) {
            std::cout << " => Error: Das löschen des Settings-Ordners ist fehlgeschlagen." << std::endl;
            return 1;
        }

    }

    //Cache Dir

    if (settings->name == "CACHE" || settings->name == "ALL") {
        if( ! removeDirIsOk(settings->cacheDir, settings, settings->askForEveryDir)) {
            std::cout << " => Error: Das löschen des Cache-Ordners ist fehlgeschlagen." << std::endl;
            return 2;
        }

    }
    else if(settings->name != "CACHE" && settings->name != "SETTINGS" && settings->name != "ALL")
    {
        std::cout << " => Error: Unbekannte Option '" << settings->name << "' für Ordnerauswahl." << std::endl;
        std::cout << "Aufruf: " << settings->programName << " --remove [OPTION]... [settings|cache|all]" << std::endl;
        std::cout << "\"" << settings->programName << " --remove --help\" liefert weitere Informationen." << std::endl;
        return 3;
    }


    return 0;
}

int ProgramManager::printPopularSeries(Settings *settings)
{
    if(settings->pagesInUse.size() < 1) {
        std::cout << " => Error Keine Internet Seiten vorhanden." << std::endl;
        return -12;
    }
    std::cout << "Pages: " << std::endl;
                 for( const auto &page : settings->pagesInUse ) {
                     std::cout << page.name_id << std::endl;
                 }

    for( const auto &page : settings->pagesInUse ) {
        std::cout <<  ((settings->colorless) ? "" : "\033[93m") << "Auf '" << page.url << "'..." << ((settings->colorless) ? "" : "\033[0m") << std::endl;

        size_t pos = 0;
        std::string html = pageManager.getServerRequest(page.protocol, page.url + page.popularSerien).html;

        if(html == "-1") {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed." << std::endl;
            return 1;
        }

        if( (pos = html.find("<div class=\"seriesListContainer row\">")) == std::string::npos ) {
            std::cout << " => Error: Konnte '<div class=\"seriesListContainer row\">' nicht finden" <<std::endl;
            return 2;
        } else {
            html.erase(0, pos + 37);

        }

        if( (pos = html.rfind("</span></h3>")) == std::string::npos ) {
            std::cout << " => Error: Konnte Position von '</span></h3>' nicht finden" <<std::endl;
            return 2;
        } else {
//            std::cout << " =>  Position von '</span></h3>'" << pos << " lingesgamt: " << html.length() << " npoos: " << std::string::npos <<std::endl;
            html.erase(pos + 12);
        }

        html = replace(html, "\r", "");
        html = replace(html, "\n", "");
        html = replace(html, "col-md-15 col-sm-3 col-xs-6", "\n");

        std::stringstream strstream(html + "\n");
        html.clear();
        std::string line;
        std::cin.clear();
        while (std::getline(strstream, line).good()) {
            if(line.find("href=") == std::string::npos)
                continue;
            if(settings->debugMode)
                std::cout << "Line: " << line << std::endl;

            size_t pos = line.find("<a href=\"");
            size_t pos2 = line.find("\" title=\"");
            if(pos == std::string::npos) {
                std::cout << " => Error: Konnte Position von '<a href=' nicht finden" <<std::endl;
                continue;
            } else if(pos2 == std::string::npos) {
                std::cout << " => Error: Konnte Position von ' title=\' nicht finden" <<std::endl;
                continue;
            }
            std::string href = line.substr(pos + 9, pos2 - pos - 9);

            if( (pos = line.find("<h3>")) == std::string::npos) {
                std::cout << " => Error: Konnte Position von '<h3>' nicht finden" <<std::endl;
                continue;
            } else if( (pos2 = line.find("<span", pos)) == std::string::npos) {
                std::cout << " => Error: Konnte Position von '<span' nicht finden" <<std::endl;
                continue;
            }
            std::string name = line.substr(pos + 4, pos2 - pos - 4);

            std::cout << " > Serie: "  << ((settings->colorless) ? "" : "\033[96m") << name << ((settings->colorless) ? "" : "\033[0m") << ": "
                      << ((settings->colorless) ? "" : "\033[92m") << "(" + replace(href,page.UrlDir, "") + ")" << ((settings->colorless) ? "" : "\033[0m") << std::endl;
        }


        if(settings->useFirstPage)
            break;
        else
            std::cout << std::endl;

    }

    return 0;
}


int ProgramManager::searchModus_update(Settings *settings)
{
    std::string list;
    std::string line;
    if(settings->pagesInUse.size() < 1) {
        std::cout << " => Error Keine Internet Seiten vorhanden." << std::endl;
        return 1290;
    }


    //darf nicht weniger werden!!

    for ( const auto &page : settings->pagesInUse ) {
        std::cout << " -> Updating '" << page.name_id << "'..." << std::endl;

        Reply reply = pageManager.getServerRequest( page.protocol, page.url + page.urlAlphabetSerienList);

        if(reply.html == "-1") {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed." << std::endl;
            else
                std::cout << " -> Warnung: " << page.UrlDir << " ist fehlgeschlagen! " << std::endl;
            continue;
        }
        else if(reply.html.find("</html>") == std::string::npos ) {
            std::cout << " => Error: Konnte </html> in searchModus_update() nicht finden." << std::endl;
            continue;
        }

        //auf anime seite noic halt auf s.to jetzt anders, näml: data-alternative-title != data-alternative-titles <--s, => data-alternative-title umfasst beides!
        std::string serienListe = replace( pageManager.grep( reply.html, "data-alternative-title" ), "</li>", "\n" );

        std::string tests[] = {"\" href=\"", "<li><a data-alternative-title", page.UrlDir, "</a>", };
        bool cont = false;
        for ( auto t : tests ) {
            if(reply.html.find( t ) == std::string::npos) {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": html doesnt contain:'" << t << "' after preparing." << std::endl;
                std::cout << " -> Warnung: Überspringe: " << page.name_id << std::endl;
                cont = true;;
            }
        }
        if(cont)
            continue;

        //...\n<li><a data-alternative-title href="/serie /stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null</a>\n...
        serienListe = replace(serienListe, "<li><a data-alternative-title", "");
        //...\n" href="/serie /stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null</a>\n...
        serienListe = replace(serienListe, "\" href=\"", "|");
        //...\n|/serie /stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null</a>\n...
        serienListe = replace(serienListe, "|" + page.UrlDir, "|/");

        std::stringstream strstream(serienListe);
        serienListe.clear();

        while (getline(strstream, line)) {
            if(line.find(" title=\"") == std::string::npos)
                continue;

            line.erase(line.find(" title="), line.find(">") - line.find(" title="));
            //...\n|/serie/ stream/2012-das-jahr-null"_weg_>2012 - Das Jahr Null</a>\n...
            line = replace(line, "\">", "|");
            //...\n|/serie/ stream/2012-das-jahr-null|2012 - Das Jahr Null</a>\n...
            line = replace(line, "</a>", "");
            //...\n|/serie/ stream/2012-das-jahr-null"_weg_>2012 - Das Jahr Null|\n...

    ///Nadia The Secret, Fushigi no Nadia|/nadia-zauberstein|Nadia und Zauberstein|seriento
            serienListe += line + "|" + page.url + "\n";
        }
        if(serienListe.length() > 0)
            serienListe.pop_back();

        //Entferne Html Sonderzeichen
        serienListe = replace(serienListe, "&amp;quot;", "\""); //

        serienListe = replace(serienListe, "&amp;", "&"); //
        serienListe = replace(serienListe, "&lt;", "<"); //
        serienListe = replace(serienListe, "&gt;", ">"); //

        serienListe = replace(serienListe, "<br />", " "); //
        serienListe = replace(serienListe, "&quot;", "\""); //
        serienListe = replace(serienListe, "&apos;", "'"); //

        list += serienListe;

    }

    //Anzahl der Serien/Zeilen vorher:
    ssize_t countBef = 0;
    std::ifstream myFileBef(settings->serienListPath );
    std::string alteListe;
    if(myFileBef.is_open()) {
        for(countBef = 0; std::getline(myFileBef, line); ++countBef) {
            //Speicher alteListe für verglkeich nach Update
            alteListe.append(line + "\n");

            //Vergeliche neue und alte list => entfernte Serien
            if(line != "" && list.find(line) == std::string::npos) {
                std::string tmp = std::string(line).erase(line.find_last_of('|'));
                std::cout << settings->setPColor(settings->Red) << "Entfernt: '" << tmp.substr(tmp.find_last_of("|") + 1) << "'" << settings->resetPColor() << std::endl;
            }
        }
        myFileBef.close();
    }

    //Schreibe die Liste in das TextFile
    std::ofstream ofs(settings->serienListPath , std::ios::trunc);
    if(!ofs.is_open()) {
        perror("Konnte SerienListe-Datei nicht öffnen");
        return 111;
    } else {
        //Schreibe Liste in das TextFile
        ofs << list << std::endl;
        ofs.close();
    }

    //Anzahl der Zeile nachher
    ssize_t countAf = 0;
    std::ifstream myFileAf(settings->serienListPath );
    if(myFileAf.is_open()) {
        for(countAf = 0; std::getline(myFileAf,line); ++countAf) {
            //Vergeliche neu mit Alt => gib neue Serien aus
            if(line != "" && alteListe.find(line) == std::string::npos) {
                std::string tmp = std::string(line).erase(line.find_last_of('|'));
                std::cout << settings->setPColor(Settings::Green) << "Neu: '" << tmp.substr(tmp.find_last_of("|") + 1) << "'" << settings->resetPColor() << std::endl;
            }
        }
        myFileAf.close();
    } else {
        perror("Konnte SerienListe-Datei nicht öffnen");
        return 112;
    }

    std::cout << settings->setPColor(Settings::Yellow) << "Serienunterschied: " << ( ((countAf - countBef) > 0) ? "+" : "") << countAf - countBef << " Serien." << settings->resetPColor() << std::endl;

    //Speicher Datum des Updates...
    ofs.open(settings->lastUpdateDateFilePath, std::ios::trunc);
    if(!ofs.is_open()) {
        perror("Konnte UpdateDate-Datei nicht öffnen");
        return 113;
    } else {
        //Schreibe Liste in das TextFile
        ofs << pageManager.getDate() << std::endl;
        ofs.close();
    }

    return 0;
}

int ProgramManager::listDir(std::string &list,std::string path, int maxDepth, bool debugMode)
{
    //Wenn Pfad zu einem TextFile geht
    if(fileExists(path)) {
        if(debugMode)
            std::cout << "INFO: Überprüfe Textdatei auf bereits gedownloadete Folgen (-C): '" << path << "'." << std::endl;

        std::ifstream ifs(path);
        if(!ifs.is_open()) {
            perror(" => Error: Konnte Textdatei nicht öffnen.");
            return -1;
        }
        list = std::string((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

        if(debugMode)
            std::cout << "Inhald des TextFiles (-C):\n" << list << std::endl << std::endl;

        return 0;

    } // Sonst normal Ordner listen
    else if(maxDepth <= 0) {
        if(debugMode)
            std::cout << "INFO: Brich Vorgang für '" << path << "' ab, da max. Anzahl an zu durchsuchende Ordner erreicht wurde." << std::endl;
        return 0;
    }
    else if(nothingExists(path)) {
        std::cout << " => Warnug: Datei oder Verzeichnis existiert nicht: '" << path << "'" << std::endl;
        return 0;
    }

    //verkleiner varibable um 1, um zu verhindern, das endlose schleife entsteht
    maxDepth--;

    if(path[path.length()-1] != '/') {
        if(path[path.length()-1] != '\\') { // Wenn kein \ oder / am ende ist
            if(path.find("/") == std::string::npos) { // wenn im namen ein / ist füge am ende / hinzu
                if(path.find("\\") == std::string::npos) { // wenn im name ein \ ist add \ to en or error
                    std::cout << " => Error: Pfad zu dem Ordner enthält kein Pfadsymbol." << std::endl;
                    return -2;
                } else {
                    path.push_back('\\');
                }
            } else {
                path.push_back('/');
            }
        }
    }

    DIR* dirp = opendir(path.c_str());
    if(!dirp) {
        perror(std::string(" => Error: Konnte Verzeichnis nicht öffnen: " + path).c_str());
        return -1;
    }
    if(debugMode)
        std::cout << "-> Durchsuche Ordner '" << path << "'..." << std::endl;

    struct dirent * dp;
    while ((dp = readdir(dirp)) != nullptr) {
        if(strcmp( dp->d_name, "." ) == 0 || strcmp ( dp->d_name, ".." ) == 0)
            continue;

        else if(dirExists((path + dp->d_name + ((path.find("/") == std::string::npos) ? "\\" : "/") ))) { //if(dp->d_type == DT_DIR) {
            listDir(list, (path + dp->d_name + ((path.find("/") == std::string::npos) ? "\\" : "/") ), maxDepth, debugMode);
        } else {
            list.append( std::string(dp->d_name) + "\n" );
            if(debugMode)
                std::cout << "  > " << dp->d_name << std::endl;
        }
    }
    closedir(dirp);
    return 0;
}

int ProgramManager::convertLink(PAGE page, std::string redirectLink, AccountManager * accountManager,
                                Settings * settings, int Staffel, int Folge, std::string allLinks)
{
    std::string folgenID = std::string((Staffel == -1 || Folge == -1 ) ? "" : "S" + std::string( (Staffel < 10) ? "0" : "" ) + std::to_string(Staffel)
                                                                            + "E" + std::string( (Folge   < 10) ? "0" : "" ) + std::to_string( Folge ) );
    std::string green = ((settings->colorless) ? "" : "\033[32m"),
                red = ((settings->colorless) ? "" : "\033[31m"),
                orange =((settings->colorless) ? "" : "\033[33m");

    if(redirectLink == "" && settings->modus == Modus::DEFAULT_MODUS) {
        if(allLinks == "") {
            std::cout << " => " << red << "KEINEN Hoster für die Folge " << replace(folgenID, "E", " E") << " gefunden." << ((settings->colorless) ? "" : "\033[0m")  << std::endl;
            if(pageManager.writeToFile(settings->outputFilePaths, std::string("KEINEN Hoster für die Folge ") + replace(folgenID, "E", " E")  + std::string(" gefunden.")) != 0) {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                return 130;
            }
        } else {
            std::cout << " => " << orange << "Keinen PASSENDEN Hoster für die Folge " << replace(folgenID, "E", " E") << " gefunden." << ((settings->colorless) ? "" : "\033[0m") << std::endl
                      << "Alle Links:" << std::endl
                      << replace( replace( replace( allLinks, "data-lang-key=\"1\"", "language=\"GerDub\"" ),
                                                                   "data-lang-key=\"2\"", "language=\"Eng\"" ), "data-lang-key=\"3\"", "language=\"GerSub\"") << std::endl;
            if(pageManager.writeToFile(settings->outputFilePaths, std::string("Keinen PASSENDEN Hoster für die Folge ") + replace(folgenID, "E", " E")  + std::string(" gefunden.")) != 0) {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                return 138;
            }
        }
        //Remove this return ??
        return 0;
    }

    for (int i = 1; i <= 3; ++i) {
        auto rEply = pageManager.getUrlAfterRedirect( page.protocol, page.url + redirectLink, settings->cookieFilePath +  "_" + page.url);
        std::string newUrl = rEply.url;

        //wenn function fehl schlug beende das Programm
        if (newUrl == "-1") {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": getUrlAfterRedirect f() failed." << std::endl;
            return 102;

            //wenn nach der Umwandlung https://seriens tream.sx/ vorhanden ist, die ist wenn der Link Ungültig war:
        } else if (newUrl == "https://s.to" || newUrl == "http://190.115.18.20/" || newUrl == "https://" + page.url || rEply.html.find("404 - Seite nicht gefunden") != std::string::npos || rEply.html.find("403 Forbidden") != std::string::npos) {
            std::cout << " => " << red << replace(folgenID, "E", " E") << ( (folgenID == "") ? "" : ": " ) << "Ungültige Url: 'https://" + page.url << redirectLink << "'"
                      << ((settings->colorless) ? "" : "\033[0m") << std::endl;
            if(settings->outputFilePaths.size() != 0)
                if(pageManager.writeToFile(settings->outputFilePaths, replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + "Ungültige Url: https://"  + page.url + redirectLink) != 0) {
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                    return 108;
                }
            return 0;
            // wenn nach der Umwandlung immern och ein redirect vorhanden ist, also wenn z.B.: account gewechselt werden muss
        } else if(newUrl.find("/redirect/") != std::string::npos ) {
            if(settings->debugMode)
                std::cout << "Warnung: Redirect Link nach umwandlung (Capcha?) --> Neuer Account" << std::endl;
            if(pageManager.login(page, accountManager->getNextAccount(), settings->cookieFilePath +  "_" + page.url) != 0) {
                if(settings->debugMode)
                    std::cerr << ">>> Debug In " << __FUNCTION__ << ": login f() failed." << std::endl;
                return -1;
            }
            continue;
            //alles ok
        } else {
            if( (newUrl = pageManager.getLinkAfterHosterBasedOperation(newUrl)) == "") {
                if(settings->debugMode)
                    std::cout << " => Error in getLinkAfterHosterBasedOperation() -> exit convertLink()" << std::endl;
                return 118;
            }

            std::cout << " => " << folgenID << ( (folgenID == "") ? "" : ": " ) << green << newUrl << ((settings->colorless) ? "" : "\033[0m") << std::endl;
            if(settings->outputFilePaths.size() != 0)
                if(pageManager.writeToFile(settings->outputFilePaths,folgenID + ( (folgenID == "") ? "" : ": " ) + newUrl) != 0) {
                    if(settings->debugMode)
                        std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
                    return 108;
                }
            return 0;
        }
    }

    //nach 3temn Versuch gib error aus:
    std::cout << " => " << replace(folgenID, "E", " E") << ( (folgenID == "") ? "" : ": " ) << red << "https://" + page.url << redirectLink << ((settings->colorless) ? "" : "\033[0m") << std::endl;
    if(settings->outputFilePaths.size() != 0) {
        if(pageManager.writeToFile(settings->outputFilePaths, replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + redirectLink) != 0) {
            if(settings->debugMode)
                std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl;
            return 114;
        }
    }
    return 0;
}


























