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

// includes from STL (for Linux) for std::auto_ptr
#include <memory>

// includes from Qt
#include <QDir>
#include <QString>
#include <QFileInfo>
#include <QVector>

// Hide warning for Exception + declspec(nothrow)
#if defined(_WIN32) && !defined(__MINGW32__) // MSVC only
#pragma warning( disable : 4290 )
#endif // MSVC only

// Dependency from cepcoreschema
// Declaration here to avoid declaration in dependant projects.
namespace cepcoreschema {
class Cep;
}

class ExtensionGenerator;

/**
 * @ingroup group_sdk_libraries_cepgenerator
 *
 * @brief
 * This class contains the entry points to generate CEP.
 *
 * A CEP is generated form an XML file or from a dom xml-schema.
 * See <a href="https://camitk.imag.fr"> wiki</a> to understand how a CEP is buildt.
 * <b>Release 3.5: Suppose that the CEP does NOT already exist. </b>
 *
 **/
class CepGenerator {
public :

    /**
    * Create a CEPGenerator from the XML file \c xmlFileName in the directory \c devDirectoryName. \n
    *
    * <b>Supposes that the CEP does NOT exist.</b>
    * Create a domCep from the XML file
    *
    **/
    CepGenerator(QString xmlFilename, QString devDirectoryName);

    /**
    * Create a CEPGenerator from the DOM XML-schema \c domCep in the directory \c devDirectoryName. \n
    *
    * <b>Supposes that the CEP does NOT exist.</b>
    *
    * \note the CepGenerator instance <b>takes ownership</b> of \c domCep. When sending your \c unique_ptr you need
    * to use \c std::move(yourDomCep) for the first parameter
    *
    **/
    CepGenerator(std::unique_ptr<cepcoreschema::Cep> domCep, QString devDirectoryName);

    /**
    * Create an empty CepGenerator
    */
    CepGenerator();

    virtual ~CepGenerator();

    /// call all methods to generate the CEP from the DomTree.
    void process();

    /// Set the input XML CEP manifest (ant check its xml validity)
    void setXmlFileName(QString xmlFileName);

    /// Create the DOM attribute domCep from the XML CEP manifest
    void createDomTree();

    /// Where to generate the CEP directories and files
    void setDevDirectoryName(QString devDirectoryName);

    /// Serialize the manifest ie serialize the domCep to a std::string
    void serializeManifest(QString fileName = "");

protected:

    /** Create the general directory tree (the same for every CEP).
      * Copies the default files in the right directories:
    \code
                cepdirectoryname
                    |
                    +--- actions
                        |
                        ---- CMakeLists.txt
                    +--- applications
                        |
                        ---- CMakeLists.txt
                    +--- components
                        |
                        ---- CMakeLists.txt
                    +--- libraries
                        |
                        --- CMakeLists.txt
                    +--- viewers
                        |
                        --- CMakeLists.txt
                    ---- COPYRIGHT
                    ---- CMakeLists.txt
                    ---- FindCamiTK.cmake
                    ---- Manifest.xml
                    ---- README
    \endcode
        */
    virtual void generateDirectoryTree();

    /** @{ Helper methods for generateDirectoryTree */

    /// Generate CMakeLists file
    virtual void generateGlobalCMakeLists();

    /// Generate copyright file
    virtual void generateCopyright();

    /// Generate Readme File
    virtual void generateReadme();

    /// Generate the FindCamiTK file
    virtual void copyFindCamiTK();

    /// Generate the Actions directory
    virtual void generateActionsDirectory();

    /// Generate the Applications directory
    virtual void generateApplicationsDirectory();

    /// Generate the Components directory
    virtual void generateComponentsDirectory();

    /// Generate the Libraries directory
    virtual void generateLibrariesDirectory();

    /// Generate the Libraries directory
    virtual void generateViewersDirectory();

    /// Set the licence ine the \c licence variable to be included later in the generated files.
    virtual void setLicence();
    /** @} */

    /**
    Create the ActionExtensionDom if needed and call the appropriate methods to generate the action extensions.
    */
    virtual void createActionExtensionDoms();

    /**
    Create the ComponentExtensionDom if needed and call the appropriate methods to generate the component extensions.
    */
    virtual void createComponentExtensionDoms();

    /**
    Create the LibrariesDom if needed and call the appropriate methods to generate the libraries.
    */
    virtual void createLibrarieDoms();

    /**
    Create the ViewersDom if needed and call the appropriate methods to generate the viewer extensions.
    */
    virtual void createViewersExtensionDoms();

    virtual void generateExtensions();

private:
    /** XML DOM Element create by CodeSynthesis
            This cep instance contains all of the informations of the xml file
        */
    std::unique_ptr<cepcoreschema::Cep> domCep;

    /// Where to find the original XML description of the CEP
    QFileInfo xmlFileName;

    /// Where to store the produced files
    QDir devDirectoryName;

    /// Subdirectory where the CEP sources will be stored (updated when generating the directory tree)
    QString cepDirectoryName;

    /// Action or Component Extensions
    QVector<ExtensionGenerator*> extensions;

    /// overall licence of the CEP
    QString licence;

};

#endif // CEPGENERATOR_H
