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

// CamiTK includes
#include <Property.h>
#include <Log.h>

// Qt wizard
#include <QRadioButton>
#include <QDebug>
#include <QLabel>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QWizard>
#include <QWizardPage>

using namespace camitk;

// -------------------- init --------------------
void NewExtensionFile::init() {
    extensionEditor = nullptr;
    setIcon(QPixmap(":/fileNew"));
}

// -------------------- process --------------------
Action::ApplyStatus NewExtensionFile::process() {
    if (extensionEditor == nullptr) {
        QString language = "Python";
        QString newExtensionName = "Sample Extension";
        QString cppGenerationType = "Standard";

        // build the wizard
        QWizard wizard;
        QWizardPage* page1 = new QWizardPage();
        QWizardPage* page2 = new QWizardPage();
        QWizardPage* page3 = new QWizardPage();
        wizard.setWindowTitle("New CamiTK Extension");

        //-- 1. Page 1: Language Selection
        page1->setTitle("Select Extension Language");
        QVBoxLayout* layoutPage1 = new QVBoxLayout;

        QLabel* languageLabel = new QLabel("Choose your extension programming language:");
        QRadioButton* pythonButton = new QRadioButton("Python");
        QString pythonExplanationText = "Python extensions are more dynamic and are defined using scripts structured to interact with CamiTK. The Python script skeleton will be generated automatically.";
        QRadioButton* cppButton = new QRadioButton("C++");
        QString cppExplanationText = "C++ extensions are compiled and are faster to load and run. C++ code structure and CMake project files will be generated automatically.";
        QLabel* explanationLabel = new QLabel();
        explanationLabel->setWordWrap(true);

        layoutPage1->addWidget(languageLabel);
        layoutPage1->addWidget(pythonButton);
        layoutPage1->addWidget(cppButton);
        layoutPage1->addWidget(explanationLabel);
        page1->setLayout(layoutPage1);

        // python by default
        pythonButton->setChecked(true);
        explanationLabel->setText(pythonExplanationText);

        QObject::connect(cppButton, &QRadioButton::toggled, [&](bool checked) {
            if (checked) {
                language = "C++";
                explanationLabel->setText(cppExplanationText);
                wizard.addPage(page3);
            }
        });
        QObject::connect(pythonButton, &QRadioButton::toggled, [&](bool checked) {
            if (checked) {
                language = "Python";
                explanationLabel->setText(pythonExplanationText);
                wizard.removePage(2);
            }
        });

        //-- 2. Page 2 – Extension Name entry
        page2->setTitle("Extension Name");
        QVBoxLayout* layoutPage2 = new QVBoxLayout();

        QLabel* topText = new QLabel("Choose your extension name:");
        QLabel* nameLabel = new QLabel("Name:");
        QLineEdit* nameEdit = new QLineEdit(newExtensionName);
        QLabel* bottomText = new QLabel("<p>Please choose wisely. This name will be used to generate the extension source code.</p><p>While renaming an extension is always possible, it should be done very carefully as a lot of static information are generated from it. Therefore, once entered here, the extension name will be presented as a <i>read only field</i>. If a rename is needed in the future, changing the extension name must be done by directly editing the .CamiTK (JSON) file.</p>");
        bottomText->setWordWrap(true);

        layoutPage2->addWidget(topText);
        layoutPage2->addWidget(nameLabel);
        layoutPage2->addWidget(nameEdit);
        layoutPage2->addWidget(bottomText);
        page2->setLayout(layoutPage2);

        QObject::connect(nameEdit, &QLineEdit::textChanged,
        [&](const QString & text) {
            newExtensionName = text;
        });

        // Page 3 – Only shown if language is C++
        page3->setTitle("C++ Type");
        auto layoutPage3 = new QVBoxLayout();

        QRadioButton* standardButton = new QRadioButton("Standard");
        QRadioButton* hotPlugButton = new QRadioButton("HotPlug (experimental)");
        QTextEdit* generationTypeExplanation = new QTextEdit(R"(<p>There are two types of extension:</p>
        <ul>
            <li>
                <b>HotPlug</b> extensions are more versatile, faster and easier to use as they are generated on the fly from
                their CamiTK extension file. The source code you need to write is kept to bare minimum. This is the only option if you are developing in Python. Even in C++, HotPlug extension gives you the possibility to avoid application restart most of the time.
                <ul>
                    <li>
                        <b>Advantages:</b> when you modify the action source code, <b>modifications are taken into account
                        immediately</b> (no need to restart) and <b>redistributing your extension is easy</b> as you just
                        need to pack the CamiTK extension file and the action source codes (even in C++, unless you have
                        developed your own libraries). In C++ you still need to rebuild your code after a modification, but
                        that's about it, no need to restart the application (although restart is still recommended after a
                        clean+rebuild or clean+reconfigure).
                    </li>
                    <li>
                        <b>Disadvantages:</b> Actions are instantiated when the application is started, which might impact the launch time and leads to <b>slower application start</b> (especially visible in C++).
                    </li>
                </ul>
            <li>
                <b>Standard</b> extensions have to be loaded classically (i.e., using the standard and only available style up to CamiTK version 5.2). It uses classic ActionExtension plugin. Only C++ extension can be made available for this type.
                <ul>
                    <li>
                        <b>Advantages: </b>startup time is faster</b> and <b>you don't need to distribute your source code</b> as everything is built and contained into a dynamic library
                    </li>
                    <li>
                        <b>Disadvantage</b> When you modify a source code, you need to go through the usual C++ development
                        steps and restart the application for your modification to be taken into account.
                    </li>
                </ul>
            </li>
        </ul>
        <p>The conversion from <i>HotPlug</i> to <i>Standard</i> can be done automatically using the extension generator but will require copy-pasting your method code. The conversion from <i>Standard</i> to <i>HotPlug</i> is also possible but all the steps will have to be done manually.</p>)");
        generationTypeExplanation->setReadOnly(true);
        generationTypeExplanation->setWordWrapMode(QTextOption::WordWrap);
        generationTypeExplanation->setFrameStyle(QFrame::NoFrame);
        generationTypeExplanation->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        generationTypeExplanation->setMinimumHeight(80);
        generationTypeExplanation->setFrameShadow(QFrame::Plain);
        //-- palette with the "normal" neutral background
        QPalette readOnlyPalette = wizard.palette();
        QColor windowBackgroundColor = readOnlyPalette.color(QPalette::Window);
        readOnlyPalette.setColor(QPalette::Base, windowBackgroundColor);
        generationTypeExplanation->setPalette(readOnlyPalette);

        layoutPage3->addWidget(standardButton);
        layoutPage3->addWidget(hotPlugButton);
        layoutPage3->addWidget(generationTypeExplanation);
        page3->setLayout(layoutPage3);

        // default
        standardButton->setChecked(true);

        QObject::connect(standardButton, &QRadioButton::toggled, [&](bool checked) {
            if (checked) {
                cppGenerationType = "Standard";
            }
        });
        QObject::connect(hotPlugButton, &QRadioButton::toggled, [&](bool checked) {
            if (checked) {
                cppGenerationType = "HotPlug";
            }
        });

        // Add first two pages to wizard unconditionally
        wizard.addPage(page1);
        wizard.addPage(page2);

        if (wizard.exec() == QDialog::Accepted) {
            if (!newExtensionName.isEmpty()) {
                extensionEditor = new CamiTKExtensionEditor(QString(), newExtensionName, language, cppGenerationType);
                connect(extensionEditor, &CamiTKExtensionEditor::extensionGeneratorPresenterClosed, this, [this ]() {
                    extensionEditor = nullptr; // no need to delete as this will be done when the windows is closed
                    actionWidget = nullptr;
                });
            }
            else {
                return Action::ABORTED;
            }
        }
        else {
            return Action::ABORTED;
        }
    }

    extensionEditor->show();
    extensionEditor->raise();

    return Action::SUCCESS;
}

// -------------------- targetDefined --------------------
void NewExtensionFile::targetDefined() {

}

// -------------------- parameterChanged --------------------
void NewExtensionFile::parameterChanged(QString parameterName) {
}