/*****************************************************************************
 * $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 "LibraryGenerator.h"

// includes from cepcoreschema
#include <Library.hxx>
#include <Dependency.hxx>

// includes from STL
#include <iostream>
#include <memory>

// includes from Qt
#include <QFileInfo>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QRegularExpression>

// local includes
#include "ClassNameHandler.h"
#include "DependencyGenerator.h"


using namespace cepcoreschema;

LibraryGenerator::LibraryGenerator(QString xmlFileName, QString actionExtensionsDirectory, QString licence)
    : ExtensionGenerator(actionExtensionsDirectory, licence, "Library") {
    QFileInfo xmlFile(xmlFileName);
    if ((! xmlFile.exists()) || (! xmlFile.isFile())) {
        throw std::invalid_argument("I/O exception during library file generation:\nFile " + xmlFileName.toStdString() + " does not exist or is not a file...\n");
    }
    try {
        std::string xmlFileStr = xmlFileName.toStdString();
        std::unique_ptr<Library>domLibrary = library(xmlFileStr, xml_schema::flags::dont_validate);
        createFromDom(*domLibrary);
    }
    catch (...) {
        throw std::invalid_argument("I/O exception during library file generation:\nFile " + xmlFileName.toStdString() + " is not valid...\n");
    }
}

LibraryGenerator::LibraryGenerator(Library& domLibrary, QString LibraryDirectory, QString licence)
    : ExtensionGenerator(LibraryDirectory, licence, "Library") {
    createFromDom(domLibrary);
}

void LibraryGenerator::createFromDom(Library& dom) {
    this->name = QString(dom.name().c_str());
    this->description = QString(dom.description().c_str()).simplified();
    this->isStatic = dom.static_();

    if (dom.dependencies().present()) {
        Dependencies deps = dom.dependencies().get();
        for (Dependencies::dependency_iterator it = deps.dependency().begin(); it != deps.dependency().end(); it++) {
            Dependency& dep = (*it);
            DependencyGenerator* depGen = new DependencyGenerator(dep);
            dependencyGenerators.append(depGen);
        }
    }


}

LibraryGenerator::~LibraryGenerator() {
//    for (QVector<DependencyGenerator *>::iterator dep = dependencyGenerators.begin(); dep != dependencyGenerators.end(); dep++)
//        delete dep;

}

void LibraryGenerator::generateExtensionCMakeLists(QString directory) {
    // Needed strings
    QString projectName = ClassNameHandler::getClassName(this->name);
    QString staticOrDynamic = "STATIC";
    if (! isStatic) {
        staticOrDynamic = "SHARED";
    }

    // Generate strings for dependencies
    QString extLibs  = DependencyGenerator::getExternalLibsString(this->dependencyGenerators);
    QString cepLibs =  DependencyGenerator::getCepLibsString(this->dependencyGenerators);
    QString neededComps = DependencyGenerator::getNeededComponentsString(this->dependencyGenerators);
    QString neededActions = DependencyGenerator::getNeededActionsString(this->dependencyGenerators);


    // Open the resources CMakeFile model
    QFile initFile(":/resources/CamiTKLibraryCMakeLists.txt.in");
    initFile.open(QIODevice::ReadOnly | QIODevice::Text);
    QTextStream in(&initFile);

    // Set the right output file name
    QFileInfo cmakelistsOutFileInfo;
    cmakelistsOutFileInfo.setFile(directory, "CMakeLists.txt");
    QFile cmakelistsOutFile(cmakelistsOutFileInfo.absoluteFilePath());
    if (! cmakelistsOutFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QString msg = "Exception from cep file generation \n    Cannot write on file " + cmakelistsOutFileInfo.absoluteFilePath() + "\n";
        throw msg;
    }

    QTextStream out(&cmakelistsOutFile);
    QString text;
    do {
        text = in.readLine();
        text.replace(QRegularExpression("@PROJECTNAME@"), projectName);
        text.replace(QRegularExpression("@PROJECTNAME_LOW@"), projectName.toLower());
        text.replace(QRegularExpression("@PROJECTNAME_HIGH@"), projectName.toUpper());
        text.replace(QRegularExpression("@STATIC_OR_DYNAMIC@"), staticOrDynamic);


        text.replace(QRegularExpression("@NEEDEDLIBS@"), extLibs);
        text.replace(QRegularExpression("@NEEDEDCEPLIBRARIES@"), cepLibs);
        text.replace(QRegularExpression("@NEEDEDCOMPEXT@"), neededComps);
        text.replace(QRegularExpression("@NEEDEDACTIONEXT@"), neededActions);
        text.replace(QRegularExpression("@LIBRARYDESCRIPTION@"), this->description);
        out << text << Qt::endl;
    }
    while (! text.isNull());
    cmakelistsOutFile.close();
    initFile.close();

}


