/*****************************************************************************
 * $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$
 ****************************************************************************/
#ifndef __EXTENSION_GENERATOR__
#define __EXTENSION_GENERATOR__

#include <QString>
#include <QJsonArray>
#include <QDir>
#include "CamiTKExtensionModel.h"
#include "TransformEngine.h"

/**
 * Extension generator
 *
 * Generate extension source code from a .camitk (JSON) that contains a "camitk"/"extensions" objects.
 *
 * Currently supported:
 * - action extensions ("actions" JSON object inside "extensions"): generates the source code for each "action" inside the array "actions"
 *
 * \note
 * In the template the extension $license$ is used for each generated source file to generate a license
 * comment at the top. $license$ can either be:
 * - a common license string (same as the one used in the debian /usr/share/common-licenses directory).
 *   Supported license strings: BSD, GPL (same as GPL-3) and LGPL (same as LGPL-3).
 * - a specific license text written in the "license" JSON string
 *
 */
class ExtensionGenerator {

public:
    /// Initialize the extension generator using the given .camitk file
    /// Note that if the outputDir does not exist, it will be created here
    /// At the end of the constructor, the camitk file is loaded in the camitkExtensionModel attribute and outputDirectoryName is a valid directory
    ExtensionGenerator(const QString& camitkFilePath, const QString& outputDirectoryName);

    virtual ~ExtensionGenerator() = default;

    /// call all methods to generate the source code
    /// Also generate CMake files and user action classes if they don't exist
    /// and the output directory is the directory of camitkFilePath (i.e. if it is the first
    /// generation)
    bool generate();

private:
    /// Where to store the generated files
    QDir outputDir;

    /// The camitk extension model loaded from the camitk extension file
    CamiTKExtensionModel camitkExtensionModel;

    /// @brief the path from where the camitk file model should be loaded
    QString camitkFilePath;

    /// Current transform engine
    TransformEngine transformEngine;

    /// current status
    bool success;

    // Accumulate messages in these list, print them to std::out only at the end of generate()
    QStringList statusMessage;
    QStringList warningMessage;

    /// @name utility
    /// @{
    /// Returns the text content of filename
    QString fileToString(const QString& filename);

    /// create the output directory
    bool createOutputDirectoryIfNeeded(const QString& dirPath);

    /// generate action extension code
    void generateActionExtension();

    /// generate HotPlug C++ action extension code (and CMake files) (does not overwrite existing files, but
    /// but the Action/CMakeLists.txt if a new action is discovered)
    void generateCppHotPlugActionExtension();

    /// generate Standard C++ user action extension code (and CMake files) (does not overwrite existing files)
    void generateCppStandardUserActionExtension();

    /// generate Standard C++ (hidden/in build) wrapper action and action extension code (always overwrite)
    void generateCppStandardWrapperActionExtension();

    /// generate Python action extension code
    void generatePythonActionExtension();

    /// is this a C++ extension
    bool isCpp();

    /// update the extension model fields with general information (licence, camitk file information
    /// and camitk installation information)
    void updateExtensionModel();

    /// update the given type (action/component/viewer/library) using the top-level extensions model information
    /// This will add "licenseComment" and "extensionDependencies" fields to each action/component/viewer/library
    void inheritFromExtension(const QString type);

    ///@}

};

#endif // __EXTENSION_GENERATOR__