/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

// -- Core stuff
#include <Core.h>
#include <AbortException.h>
#include <Log.h>

#include <QRegularExpression>

#include <iostream>
#include <vector>

using namespace camitk;

void usage(std::string programName) {
    std::cerr << "usage: " << programName << " -d path" << std::endl;
    std::cerr << "\t-d path\tdirectory to write the log file to" << std::endl;
    std::cerr << Core::version() << std::endl;
}


QString cleanUp(QString input) {
    // remove full path (as build dir can be in different places)
    return input.replace(QRegularExpression("^.*/tutorials"), "$CMAKE_BINARY_DIR/tutorials");
}

int main(int argc, char* argv[]) {
    std::vector<std::string> argList(argv, argv + argc);
    std::exception_ptr otherException;
    try {
        if (argList.size() < 3) {
            usage(argList[0]);
            return EXIT_SUCCESS;
        }

        if (argList[1] != "-d") {
            std::cerr << "Argument errors: unknown argument \"" << argList[1] << "\"" << std::endl;
            usage(argList[0]);
            return EXIT_FAILURE;
        }

        QDir logDir(argList[2].c_str());
        if (!logDir.exists() && !logDir.mkpath(argList[2].c_str())) {
            std::cerr << "Argument errors: directory \"" << argList[2] << "\" does not exits and cannot be created." << std::endl;
            usage(argList[0]);
            return EXIT_FAILURE;
        }

        // Test CamiTK basic logger
        // Set logger parameters so that it can be compared reproductivily
        Log::getLogger()->setTimeStampInformation(false);
        // Cannot have any message box (no main application therefore no QWidget can be instantiated)
        Log::getLogger()->setMessageBoxLevel(InterfaceLogger::NONE);
        // so that the filename (that contains the time stamp) is not printed
        Log::getLogger()->setLogLevel(InterfaceLogger::INFO);
        Log::getLogger()->setLogToFile(true);

        // Start test: this message should be visible as default level for CamiTK logger is warning
        CAMITK_WARNING_ALT("Application testlogger started. Log directory:" + cleanUp(logDir.canonicalPath()))

        CAMITK_WARNING_ALT("This is a test message. Next instruction crashes the application. Log file should still be ok")

        abort();

        CAMITK_WARNING_ALT("Application testlogger finished. This message should not appear in the log.")
        return EXIT_SUCCESS;
    }
    catch (const camitk::AbortException& e) {
        std::cerr << argList[0] << "aborted by CamiTK abort exception: " << e.what() << "." << std::endl;
        return EXIT_FAILURE;
    }
    catch (const std::exception& e) {
        std::cerr << argList[0] << "aborted by std exception: " << e.what() << "." << std::endl;
        return EXIT_FAILURE;
    }
    catch (...) {
        std::cerr << argList[0] << "aborted by unknown exception" << std::endl;
        otherException = std::current_exception();
        try {
            if (otherException) {
                std::rethrow_exception(otherException);
            }
        }
        catch (const std::exception& e) {
            std::cerr << ": " << e.what() << ".";
        }
        std::cerr << std::endl;
        return EXIT_FAILURE;
    }
}

