/**
 * UGENE - Integrated Bioinformatics Tools.
 * Copyright (C) 2008-2023 UniPro <ugene@unipro.ru>
 * http://ugene.net
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */

#pragma once

#include <QStandardItem>
#include <QWizard>

#include "library/CfgExternalToolModel.h"
#include "ui_CreateCmdlineBasedWorkerWizardCommandPage.h"
#include "ui_CreateCmdlineBasedWorkerWizardElementAppearancePage.h"
#include "ui_CreateCmdlineBasedWorkerWizardGeneralSettingsPage.h"
#include "ui_CreateCmdlineBasedWorkerWizardInputDataPage.h"
#include "ui_CreateCmdlineBasedWorkerWizardOutputDataPage.h"
#include "ui_CreateCmdlineBasedWorkerWizardParametersPage.h"
#include "ui_CreateCmdlineBasedWorkerWizardSummaryPage.h"

namespace U2 {

class ExternalProcessConfig;
class ExternalTool;
class ExternalToolSelectComboBox;

class CreateCmdlineBasedWorkerWizard : public QWizard {
    Q_OBJECT
public:
    explicit CreateCmdlineBasedWorkerWizard(SchemaConfig* schemaConfig, QWidget* parent = nullptr);
    explicit CreateCmdlineBasedWorkerWizard(SchemaConfig* schemaConfig, ExternalProcessConfig* initialConfig, QWidget* parent = nullptr);
    ~CreateCmdlineBasedWorkerWizard() override;

    ExternalProcessConfig* takeConfig();

    static void saveConfig(ExternalProcessConfig* config);
    static bool isRequiredToRemoveElementFromScene(ExternalProcessConfig* actualConfig, ExternalProcessConfig* newConfig);

    static const QString PAGE_TITLE_STYLE_SHEET;

    static const QString ATTRIBUTES_DATA_FIELD;
    static const QString ATTRIBUTES_IDS_FIELD;
    static const QString ATTRIBUTES_NAMES_FIELD;
    static const QString COMMAND_TEMPLATE_DESCRIPTION_FIELD;
    static const QString COMMAND_TEMPLATE_FIELD;
    static const QString CUSTOM_TOOL_PATH_FIELD;
    static const QString INPUTS_DATA_FIELD;
    static const QString INPUTS_IDS_FIELD;
    static const QString INPUTS_NAMES_FIELD;
    static const QString INTEGRATED_TOOL_ID_FIELD;
    static const QString USE_INTEGRATED_TOOL_FIELD;
    static const QString OUTPUTS_DATA_FIELD;
    static const QString OUTPUTS_IDS_FIELD;
    static const QString OUTPUTS_NAMES_FIELD;
    static const QString WORKER_DESCRIPTION_FIELD;
    static const QString WORKER_ID_FIELD;
    static const QString WORKER_NAME_FIELD;

private slots:
    void accept() override;

private:
    void init();
    ExternalProcessConfig* createActualConfig() const;

    ExternalProcessConfig* initialConfig;
    ExternalProcessConfig* config;
    SchemaConfig* schemaConfig;
};

class CreateCmdlineBasedWorkerWizardGeneralSettingsPage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardGeneralSettingsPage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardGeneralSettingsPage(ExternalProcessConfig* initialConfig);

    void initializePage() override;
    bool isComplete() const override;
    bool validatePage() override;

signals:
    void si_integratedToolChanged();

private slots:
    void sl_browse();
    void sl_integratedToolChanged();

private:
    static void makeUniqueWorkerName(QString& name);

    ExternalProcessConfig* initialConfig;
    ExternalToolSelectComboBox* cbIntegratedTools;

    static char const* const INTEGRATED_TOOL_ID_PROPERTY;
    static char const* const WORKER_ID_PROPERTY;
    static const QString LOD_DOMAIN;
};

class CreateCmdlineBasedWorkerWizardInputDataPage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardInputDataPage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardInputDataPage(ExternalProcessConfig* initialConfig);

    void initializePage() override;
    bool isComplete() const override;

signals:
    void si_inputsChanged();

private slots:
    void sl_addInput();
    void sl_deleteInput();
    void sl_updateInputsProperties();

private:
    ExternalProcessConfig* initialConfig;
    CfgExternalToolModel* inputsModel;

    static char const* const INPUTS_DATA_PROPERTY;
    static char const* const INPUTS_IDS_PROPERTY;
    static char const* const INPUTS_NAMES_PROPERTY;
};

class CreateCmdlineBasedWorkerWizardParametersPage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardParametersPage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardParametersPage(ExternalProcessConfig* initialConfig, SchemaConfig* schemaConfig);

    void initializePage() override;
    bool isComplete() const override;

signals:
    void si_attributesChanged();

private slots:
    void sl_addAttribute();
    void sl_deleteAttribute();
    void sl_updateAttributes();

private:
    static void initAttributesModel(QAbstractItemModel* model, const QList<AttributeConfig>& attributeConfigs);

    ExternalProcessConfig* initialConfig;

    CfgExternalToolModelAttributes* model;

    static char const* const ATTRIBUTES_DATA_PROPERTY;
    static char const* const ATTRIBUTES_IDS_PROPERTY;
    static char const* const ATTRIBUTES_NAMES_PROPERTY;
};

class CreateCmdlineBasedWorkerWizardOutputDataPage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardOutputDataPage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardOutputDataPage(ExternalProcessConfig* initialConfig);

    void initializePage() override;
    bool isComplete() const override;

signals:
    void si_outputsChanged();

private slots:
    void sl_addOutput();
    void sl_deleteOutput();
    void sl_updateOutputsProperties();

private:
    ExternalProcessConfig* initialConfig;
    CfgExternalToolModel* outputsModel;

    static char const* const OUTPUTS_DATA_PROPERTY;
    static char const* const OUTPUTS_IDS_PROPERTY;
    static char const* const OUTPUTS_NAMES_PROPERTY;
};

class CommandValidator : public QObject {
    Q_OBJECT
public:
    CommandValidator(QTextEdit* textEdit);

private slots:
    void sl_textChanged();

private:
    QTextEdit* textEdit;
};

class CreateCmdlineBasedWorkerWizardCommandPage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardCommandPage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardCommandPage(ExternalProcessConfig* initialConfig);

    void initializePage() override;
    bool isComplete() const override;
    bool validatePage() override;

private:
    ExternalProcessConfig* initialConfig;
};

class CreateCmdlineBasedWorkerWizardElementAppearancePage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardElementAppearancePage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardElementAppearancePage(ExternalProcessConfig* initialConfig);

    void initializePage() override;

private:
    ExternalProcessConfig* initialConfig;
};

class CreateCmdlineBasedWorkerWizardSummaryPage : public QWizardPage, private Ui_CreateCmdlineBasedWorkerWizardSummaryPage {
    Q_OBJECT
public:
    CreateCmdlineBasedWorkerWizardSummaryPage();

private:
    void showEvent(QShowEvent* event) override;
};

class ExternalToolSelectComboBox : public QComboBox {
    Q_OBJECT
public:
    ExternalToolSelectComboBox(QWidget* parent = nullptr);

    virtual void hidePopup() override;

    void modifyMenuAccordingToData(const QString& data);
    void setDefaultMenuValue(const QString& defaultValue);

private:
    void addSupportedToolsPopupMenu();
    void initExternalTools();
    void initPopupMenu();
    void separateSupportedAndCustomTools(const QList<ExternalTool*>& tools);
    void makeSupportedToolsMapFromList(const QList<ExternalTool*>& tools);
    void sortCustomToolsList();
    void sortSupportedToolsMap();
    void initFirstClickableRow();

    // exclude module and runner tools
    static void excludeNotSuitableTools(QList<ExternalTool*>& tools);

    QMap<QString, QList<ExternalTool*>> supportedTools;
    QList<ExternalTool*> customTools;
    QString firstClickableRowData;

    static const QString SHOW_ALL_TOOLS;
    static const QString SHOW_CUSTOM_TOOLS;
};

}  // namespace U2
// namespace U2
