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

// Import .h file
#include "WizardController.h"

//Imports from Qt
#include <QFinalState>

// States
#include "WizardState.h"

// Include Widgets
#include "WizardMainWindow.h"

#include "WelcomeWidget.h"
#include "CepCreateOrModifyWidget.h"
#include "CepCreationDirectoryWidget.h"
#include "CepCreationDirectoryState.h"

#include "CepDescriptionWidget.h"
#include "CepDescriptionState.h"

#include "CepContactWidget.h"
#include "CepContactState.h"

#include "CepCreateRecapWidget.h"
#include "CepCreateRecapState.h"

#include "GeneratingCEPWidget.h"
#include "GeneratingCEPState.h"

#include "ActionExtensionCreationState.h"
#include "ViewerExtensionCreationState.h"
#include "ComponentExtensionCreationState.h"
#include "LibraryCreationState.h"


#include <Cep.hxx>
#include <Contact.hxx>

#include <iostream>


WizardController::WizardController() {

    this->mainWindow = new WizardMainWindow();
    devDirectoryName = "Hello World";
    cepcoreschema::Contact c;
    this->domCep = new cepcoreschema::Cep("CEP not yet defined...", c, "to be defined");

    // Welcome
    auto* welcomeWidget = new WelcomeWidget(nullptr);
    WizardState* welcomeState = new WizardState("Welcome",  welcomeWidget, mainWindow);
    // Create a new CEP or work on an existing one ?
    // CS: Release 5 Sprint 8 [3.5 Wizard] "modifier un CEP existant"
    //CepCreateOrModifyWidget * cepCreateOrModifyWidget = new CepCreateOrModifyWidget(nullptr);
    //WizardState * cepCreateOrModifyState = new WizardState("Create / Modify a CEP ?", cepCreateOrModifyWidget, mainWindow);
    // Create the state where to enter the directory for a cep creation
    auto* cepCreationDirectoryWidget = new CepCreationDirectoryWidget(nullptr);
    CepCreationDirectoryState* cepCreationDirectoryState = new CepCreationDirectoryState("Creation Directory", cepCreationDirectoryWidget, mainWindow, &devDirectoryName);
    // CEP general description
    auto* cepDescriptionWidget = new CepDescriptionWidget(nullptr);
    CepDescriptionState* cepDescriptionState = new CepDescriptionState("CEP Description", cepDescriptionWidget, mainWindow, domCep);
    // CEP contact and licence
    auto* cepContactWidget = new CepContactWidget(nullptr);
    CepContactState* cepContactState = new CepContactState("CEP contact and licence", cepContactWidget, mainWindow, domCep);
    // CEP Recap
    auto* cepCreateRecapWidget = new CepCreateRecapWidget(nullptr);
    CepCreateRecapState* cepCreateRecapState = new CepCreateRecapState("CEP Recap", cepCreateRecapWidget, mainWindow, domCep);

    // --------------------------     Action extensions
    ActionExtensionCreationState* actionExtensionCreationState = new ActionExtensionCreationState("Action Extension State", mainWindow, domCep);

    // --------------------------     Viewer extensions
    ViewerExtensionCreationState* viewerExtensionCreationState = new ViewerExtensionCreationState("Viewer Extension State", mainWindow, domCep);

    // --------------------------     Component extensions
    ComponentExtensionCreationState* componentExtensionCreationState = new ComponentExtensionCreationState("Component Extension State", mainWindow, domCep);
    // --------------------------     Libraries
    QMap<QString, QStringList>* libraryCopyFilesMap = new QMap<QString, QStringList>();
    LibraryCreationState* libraryCreationState = new LibraryCreationState("Library Creation State", mainWindow, domCep, libraryCopyFilesMap);

    auto* generatingCEPWidget = new GeneratingCEPWidget(nullptr);
    GeneratingCEPState* generatingCEPState = new GeneratingCEPState("Generating CEP...", generatingCEPWidget, mainWindow, domCep, &devDirectoryName, libraryCopyFilesMap);


    // Quit state...
    auto* finalState = new QFinalState();


    machine.addState(welcomeState);
    // CS: Release 5 Sprint 8 [3.5 Wizard] "modifier un CEP existant" Remove this state
    // machine.addState(cepCreateOrModifyState);
    machine.addState(cepCreationDirectoryState);
    machine.addState(cepDescriptionState);
    machine.addState(cepContactState);
    machine.addState(cepCreateRecapState);

    machine.addState(actionExtensionCreationState);
    machine.addState(viewerExtensionCreationState);
    machine.addState(componentExtensionCreationState);
    machine.addState(libraryCreationState);

    machine.addState(generatingCEPState);

    machine.addState(finalState);

    // Adding transitions...
    machine.setInitialState(welcomeState);

    // CS: Release 5 Sprint 8 [3.5 Wizard] "modifier un CEP existant" link this state directly with the "choose directory state"
    // welcomeState->addTransition(welcomeWidget, SIGNAL(next()), cepCreateOrModifyState);
    welcomeState->addTransition(welcomeWidget, SIGNAL(next()), cepCreationDirectoryState);

    // CS: Release 5 Sprint 8 [3.5 Wizard] "modifier un CEP existant"
    //cepCreateOrModifyState->addTransition(cepCreateOrModifyWidget, SIGNAL(backCep()), welcomeState);
    //cepCreateOrModifyState->addTransition(cepCreateOrModifyWidget, SIGNAL(newCep()), cepCreationDirectoryState);

    // CS: Release 5 Sprint 8 [3.5 Wizard] "modifier un CEP existant"
    //cepCreationDirectoryState->addTransition(cepCreationDirectoryWidget, SIGNAL(previous()), cepCreateOrModifyState);
    cepCreationDirectoryState->addTransition(cepCreationDirectoryWidget, SIGNAL(previous()), welcomeState);
    cepCreationDirectoryState->addTransition(cepCreationDirectoryWidget, SIGNAL(next()), cepDescriptionState);

    cepDescriptionState->addTransition(cepDescriptionWidget, SIGNAL(previous()), cepCreationDirectoryState);
    cepDescriptionState->addTransition(cepDescriptionWidget, SIGNAL(next()), cepContactState);

    cepContactState->addTransition(cepContactWidget, SIGNAL(previous()), cepDescriptionState);
    cepContactState->addTransition(cepContactWidget, SIGNAL(next()), cepCreateRecapState);

    cepCreateRecapState->addTransition(cepCreateRecapWidget, SIGNAL(addActionExtension()), actionExtensionCreationState);
    actionExtensionCreationState->addTransition(actionExtensionCreationState, SIGNAL(next()), cepCreateRecapState);

    cepCreateRecapState->addTransition(cepCreateRecapWidget, SIGNAL(addViewerExtension()), viewerExtensionCreationState);
    viewerExtensionCreationState->addTransition(viewerExtensionCreationState, SIGNAL(next()), cepCreateRecapState);

    cepCreateRecapState->addTransition(cepCreateRecapWidget, SIGNAL(addComponentExtension()), componentExtensionCreationState);
    componentExtensionCreationState->addTransition(componentExtensionCreationState, SIGNAL(next()), cepCreateRecapState);

    cepCreateRecapState->addTransition(cepCreateRecapWidget, SIGNAL(addLibrary()), libraryCreationState);
    libraryCreationState->addTransition(libraryCreationState, SIGNAL(next()), cepCreateRecapState);

    cepCreateRecapState->addTransition(cepCreateRecapWidget, SIGNAL(next()), generatingCEPState);
    generatingCEPState->addTransition(generatingCEPWidget, SIGNAL(next()), finalState);

    QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));

}


WizardController::~WizardController() {
    delete domCep;
    delete mainWindow;
}


void WizardController::launch() {
    machine.start();
    mainWindow->show();
}




