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

// -- Application Imp stuff
#include "ImpMainWindow.h"

#include <sstream>

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

using namespace camitk;

// CLI stuff
#include "CommandLineOptions.hxx"

// Complete description
// If you modify this description, PLEASE do not forget to
// also update the associated "camitk-imp-prologue.1.in" man page
// (both texts should only be marginally different)

const char* description = "Please visit http://camitk.imag.fr for more information.\n"
                          "(c) Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, France\n"
                          "camitk-imp is a medical image analysis and modeling software.\n"
                          "This is the flagship GUI application of a larger framework called CamiTK\n"
                          "(Computer Assisted Medical Interventions Tool Kit) designed to ease the\n"
                          "collaborative work of a research team.\n\n"
                          "The targeted users are in R&D departments or laboratories.\n"
                          "camitk-imp provides an easy and interactive access to all your data and\n"
                          "algorithm parameters.\n\n"
                          "camitk-imp can visualize medical images from a lot of different (standard)\n"
                          "formats, offers image processing and segmentation algorithms to reconstruct a\n"
                          "mesh geometry and run a biomechanical simulation.\n\n"
                          "For a tutorial on camitk-imp, please visit the website:\n"
                          "https://camitk.imag.fr\n\n"
                          "CamiTK is highly modular and make an extensive use of extensions (plugins).\n\n"
                          "CamiTK goals are to:\n"
                          "- Gather knowledge & know-how from several fields\n"
                          "- Avoid reinventing the wheel\n"
                          "- Accelerate the integration/validation of new algorithms\n"
                          "- Provide fast technological transfer between students (PhD and others), \n"
                          "  research scientists, clinicians and industrial partners\n"
                          "- Rapidly provide a stable and usable prototype for clinicians\n"
                          "- Support for lectures and dissemination";

// usage for this application
void usage(char* appName) {
    std::cerr << appName << std::endl;
    std::cerr << std::endl;
    std::cerr << "Usage: " << appName << " [options] <file>" << std::endl;
    std::cerr << "Built using " << Core::version() << std::endl;
    std::cerr << std::endl;
    std::cout << description << std::endl;
    std::cout << std::endl;
    std::cerr << "Options:" << std::endl;
    options::print_usage(std::cerr);

    std::cout << "Arguments:" << std::endl;
    std::cout << "  <file>                Document(s) to open" << std::endl;
}


int main(int argc, char* argv[]) {
    try {
        int end; // End of options.
        options o(argc, argv, end);

        // if specific help or no options provided
        if (o.help()) {
            usage(argv[0]);
            return EXIT_SUCCESS;
        }
        else {
            // print all types of versions (just using the char* defined in CamiTKVersion.h at configuration time)
            if (o.version()) {
                std::cout << argv[0] << " build using " << Core::version() << std::endl;
                return EXIT_SUCCESS;
            }
            else {
                // capture all stdout and stderr temporarily
                std::stringstream tempOutBuffer;
                std::streambuf* backupOutBuff = std::cout.rdbuf(tempOutBuffer.rdbuf());
                std::stringstream tempErrBuffer;
                std::streambuf* backupErrBuff = std::cerr.rdbuf(tempErrBuffer.rdbuf());

                // define default log levels for imp
                Log::getLogger()->setLogLevel(InterfaceLogger::INFO);
                Log::getLogger()->setMessageBoxLevel(InterfaceLogger::WARNING);
                Log::getLogger()->setDebugInformation(true);
                CAMITK_INFO_ALT("Logger started. To change log settings, go to \"Edit → Preferences → General → camitk-imp\"")

                // init the camitk application context
                Application a("camitk-imp", argc, argv, true, true, true);

                // set the ImpMainWindow as the main window, and redirect if the --no-console option is not given
                a.setMainWindow(new ImpMainWindow(), !o.no_console());

                if (o.no_console()) {
                    // nothing is redirected to the GUI console
                    // just print the buffered stream to stdout and stderr...
                    std::cout.rdbuf(backupOutBuff);
                    std::cerr.rdbuf(backupErrBuff);
                }

                // check for given filenames
                for (int i = end; i < argc; i++) {
                    Application::open(argv[i]);
                }

                // now that the GUI/output console is in place
                // send the buffered output to the console
                std::cout << tempOutBuffer.str() << std::endl;
                std::cerr << tempErrBuffer.str() << std::endl;

                return a.exec();
            }
        }
    }
    catch (const cli::exception& e) {
        std::cerr << e << std::endl;
        usage(argv[0]);
        return EXIT_FAILURE;
    }
    catch (const camitk::AbortException& e) {
        std::cout << argv[0] << " aborted..." << std::endl << "camitk AbortException:" << std::endl << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    catch (const std::exception& e) {
        std::cout << argv[0] << " aborted..." << std::endl << "std exception:" << std::endl << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    catch (...) {
        std::cout << argv[0] << " aborted..." << std::endl << "Unknown Exception" << std::endl;
        return EXIT_FAILURE;
    }

}
