/*****************************************************************************
 * $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$
 ****************************************************************************/

// include to get a valid applicationDirPath
#include <QCoreApplication>

// include for the extension generator
#include <ExtensionGenerator.h>

// just for CamiTK version
#include <CurrentCamiTKVersion.h>

// includes from std
#include <iostream>

// CLI stuff
#include "CommandLineOptions.hxx"

// description of the application. Please update the manpage-prologue.1.in also if you modify this string.
const char* description = "camitk-extensiongenerator creates CamiTK Extension source code from\n"
                          "a description given in a .camitk (JSON) file.\n\n"
                          "Please visit https://camitk.imag.fr for more information.\n"
                          "(c) Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, France";

void usage(std::string msg = "") {
    if (msg != "") {
        std::cerr << msg << std::endl;
    }
    std::cerr << "Usage: camitk-extensiongenerator [options]" << std::endl << std::endl;
    std::cerr << description << std::endl;
    std::cerr << std::endl;
    std::cerr << "Version: " << currentCamiTKVersion << std::endl;
    std::cerr << std::endl;
    std::cerr << "Options:" << std::endl;
    options::print_usage(std::cerr);
}

/**
 * @ingroup group_sdk_application_extensiongenerator
 *
 * @brief
 * The main of the extension generator application.
 *
 */
int main(int argc, char* argv[]) {
    std::exception_ptr otherException;
    try {
        int end; // End of options.
        options o(argc, argv, end);

        // if specific help or no options provided
        if (o.help() || (o.file().empty() && o.directory().empty())) {
            usage();
            return EXIT_SUCCESS;
        }

        // print the CamiTK version
        if (o.version()) {
            std::cout << "camitk-extensiongenerator build using " << currentCamiTKVersion << std::endl;
            return EXIT_SUCCESS;
        }

        // file is mandatory
        if (o.file().empty()) {
            usage("Argument error: please provide an input .camitk JSON file.");
            return EXIT_FAILURE;
        }

        // directory is mandatory
        if (o.directory().empty()) {
            usage("Argument error: please provide an output directory.");
            return EXIT_FAILURE;
        }

        // now we can work!
        QCoreApplication app(argc, argv); // to ensure QCoreApplication::applicationDirPath is valid in ExtensionGenerator
        // TODO move to https://doc.qt.io/qt-5/qcommandlineparser.html
        // for argument parsing see https://doc.qt.io/qt-5/qcoreapplication.html#accessing-command-line-arguments
        ExtensionGenerator generator(QString::fromLocal8Bit(o.file().c_str()), QString::fromLocal8Bit(o.directory().c_str()));
        generator.generate();

        return EXIT_SUCCESS;
    }
    catch (const cli::exception& e) {
        std::cerr << "camitk-extensiongenerator aborted due to invalid arguments: " << e.what() << "." << std::endl;
        e.print(std::cerr);
        std::cerr << std::endl;
        usage();
        return EXIT_FAILURE;
    }
    catch (const std::exception& e) {
        std::cerr << "camitk-extensiongenerator aborted by std exception: " << e.what() << "." << std::endl;
        return EXIT_FAILURE;
    }
    catch (...) {
        std::cerr << "camitk-extensiongenerator 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;
    }

}

