#include "PreprocessingTab.h"

#include "RTMSimulator.h"
#include "ExaminerViewer.h"
#include "SimNode.h"

#include <QBoxLayout>
#include <QGroupBox>

#include <QLabel>
#include <QPushButton>
#include <QSpacerItem>
#include <QLineEdit>
#include <QCheckBox>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QFileDialog>
#include <QSettings>

/**
 * This is the constructor we use to create a new PreprocessingTab object.\n
 * It is mandatory to pass a pointer to a RTMSimulator object, because we create connections to the RTMSimulator object inside this constructor.
 * @param simulator A pointer to the RTMSimulator object the new PreprocessingTab will be used for.
 * @param parent A pointer to the parent QWidget object.
 * @returns A new PreprocessingTab object.
 */
PreprocessingTab::PreprocessingTab(RTMSimulator* simulator, QWidget* parent) :
        RTMTabWidget(parent),
        m_pSimulator(simulator)
{
    int nLineEditLength = 60;
    int nLabelLength = 110;

    QGroupBox* pImportDataGroupBox = new QGroupBox;
    pImportDataGroupBox->setTitle(tr("Import / Export Data"));
    QGroupBox* pSweepGroupBox = new QGroupBox;
    pSweepGroupBox->setTitle(tr("Sweep"));
    QGroupBox* pInjectionGroupBox = new QGroupBox;
    pInjectionGroupBox->setTitle(tr("Injection Settings"));
    QGroupBox* pCellSettingsGroupBox = new QGroupBox;
    pCellSettingsGroupBox->setTitle(tr("Cell Settings"));
    m_pBoxLayout->addWidget(pImportDataGroupBox);
    m_pBoxLayout->addWidget(pSweepGroupBox);
    m_pBoxLayout->addWidget(pInjectionGroupBox);
    m_pBoxLayout->addWidget(pCellSettingsGroupBox);
    pImportDataGroupBox->setFixedWidth(m_BoxWidth);
    pSweepGroupBox->setFixedWidth(m_BoxWidth);
    pInjectionGroupBox->setFixedWidth(m_BoxWidth);
    pCellSettingsGroupBox->setFixedWidth(m_BoxWidth);

    QHBoxLayout* pDataLayout = new QHBoxLayout;
    QVBoxLayout* pSweepLayout = new QVBoxLayout;
    QGridLayout* pInjectionPointLayout = new QGridLayout;
    QGridLayout* pCellSettingsLayout = new QGridLayout;
    pImportDataGroupBox->setLayout(pDataLayout);
    pSweepGroupBox->setLayout(pSweepLayout);
    pInjectionGroupBox->setLayout(pInjectionPointLayout);
    pCellSettingsGroupBox->setLayout(pCellSettingsLayout);

    QPushButton* pButtonImportMSCFile = new QPushButton;
    QPushButton* pButtonExportToFile = new QPushButton;
    pDataLayout->addWidget(pButtonImportMSCFile);
    pDataLayout->addWidget(pButtonExportToFile);
    pButtonImportMSCFile->setText(tr("Open"));
    pButtonExportToFile->setText(tr("Save to File"));


    QHBoxLayout* pSweepDistanceLayout = new QHBoxLayout;
    QLabel* pSweepLabel = new QLabel(tr("Min. Distance:"));
    pSweepDistanceLayout->addWidget(pSweepLabel);
    pSweepDistanceLayout->addStretch();

    m_pSweepDistanceFactorEdit->setFixedWidth(nLineEditLength);
    m_pSweepDistanceFactorEdit->setText("0.2");
    pSweepDistanceLayout->addWidget(m_pSweepDistanceFactorEdit);
    QHBoxLayout* pSweepButtonsLayout = new QHBoxLayout;
    QPushButton* pButtonSweep = new QPushButton;
    pSweepButtonsLayout->addWidget(pButtonSweep);
    pButtonSweep->setText(tr("Sweep"));
    connect(pButtonSweep, SIGNAL(clicked()), this, SLOT(buttonSweepClicked()));
    QPushButton* pButtonSweepOnce = new QPushButton;
    pSweepButtonsLayout->addWidget(pButtonSweepOnce);
    pButtonSweepOnce->setText(tr("Sweep once"));
    connect(pButtonSweepOnce, SIGNAL(clicked()),this,SLOT(buttonSweepOnceClicked()));
    QHBoxLayout* pSweepButtonsDeleteLayout = new QHBoxLayout;
    QPushButton* pButtonDeleteSweptNodes = new QPushButton;
    pSweepButtonsDeleteLayout->addWidget(pButtonDeleteSweptNodes);
    pButtonDeleteSweptNodes->setText(tr("Delete Swept"));
    connect(pButtonDeleteSweptNodes,SIGNAL(clicked()),this,SLOT(buttonDeleteSweptNodesClicked()));
    QHBoxLayout* pSweepButtonsReactivateLayout = new QHBoxLayout;
    QPushButton* pButtonReactivateSweptNodes = new QPushButton;
    pSweepButtonsReactivateLayout->addWidget(pButtonReactivateSweptNodes);
    pButtonReactivateSweptNodes->setText(tr("Reactivate Swept"));
    connect(pButtonReactivateSweptNodes,SIGNAL(clicked()),this,SLOT(buttonReactivateSweptNodesClicked()));
    pSweepLayout->addLayout(pSweepDistanceLayout);
    pSweepLayout->addLayout(pSweepButtonsLayout);
    pSweepLayout->addLayout(pSweepButtonsDeleteLayout);
    pSweepLayout->addLayout(pSweepButtonsReactivateLayout);

    m_pCheckBoxShowSweptNodes = new QCheckBox;
    pSweepLayout->addWidget(m_pCheckBoxShowSweptNodes);
    m_pCheckBoxShowSweptNodes->setText(tr("Show Swept Nodes"));
    connect(m_pCheckBoxShowSweptNodes, SIGNAL(stateChanged(int)), m_pSimulator, SLOT(showSweptNodes(int)));
    m_pCheckBoxShowNeighbors = new QCheckBox;
    pSweepLayout->addWidget(m_pCheckBoxShowNeighbors);
    m_pCheckBoxShowNeighbors->setText(tr("Mark Neighbors"));
    connect(m_pCheckBoxShowNeighbors, SIGNAL(stateChanged(int)), m_pSimulator, SLOT(showNeighbors(int)));
    m_pCheckBoxShowDirectNeighbors = new QCheckBox;
    pSweepLayout->addWidget(m_pCheckBoxShowDirectNeighbors);
    m_pCheckBoxShowDirectNeighbors->setText(tr("Mark Direct Neighbors"));
    connect(m_pCheckBoxShowDirectNeighbors, SIGNAL(stateChanged(int)), m_pSimulator, SLOT(showDirectNeighbors(int)));

    QLabel* pMedianCellDistanceLabel = new QLabel(tr("Median Cell Distance:"));
    QLabel* pCurrentPressureLabel = new QLabel(tr("Current Pressure:"));
    QLabel* pNumberOfSelectedNodesLabel = new QLabel(tr("Selected Cells:"));
    pMedianCellDistanceLabel->setFixedWidth(nLabelLength);
    pCurrentPressureLabel->setFixedWidth(nLabelLength);
    pNumberOfSelectedNodesLabel->setFixedWidth(nLabelLength);

    m_pInjectionPointCheckBox = new QCheckBox(tr("Injection Point"));
    m_pInjectionPointCheckBox->setTristate(false);

    QValidator *validator = new QIntValidator(0, 50000000, this);
    m_pDiameterValidator = new QDoubleValidator(0.0,100.0,10,this);
    QLabel* pInjectionPressureLabel = new QLabel(tr("Injection Pressure:"));
    QLabel* pInjectionDiameterLabel = new QLabel(tr("Injection Diameter"));
    pInjectionPressureLabel->setFixedWidth(nLabelLength);
    pInjectionDiameterLabel->setFixedWidth(nLabelLength);
    m_pInjectionPressureLineEdit = new QLineEdit;
    m_pInjectionPressureLineEdit->setFixedWidth(nLineEditLength);
    m_pInjectionPressureLineEdit->setValidator(validator);
    m_pInjectionDiameterLineEdit = new QLineEdit;
    m_pInjectionDiameterLineEdit->setFixedWidth(nLineEditLength);
    m_pInjectionDiameterLineEdit->setValidator(m_pDiameterValidator);
    QLabel* pLabelInjectionPressureUnit = new QLabel(tr("Pa"));
    QLabel* pLabelInjectionDiameterUnit = new QLabel(tr("m"));
    pInjectionPointLayout->addWidget(m_pInjectionPointCheckBox,0,0);
    pInjectionPointLayout->addWidget(pInjectionPressureLabel,1,0);
    pInjectionPointLayout->addWidget(m_pInjectionPressureLineEdit,1,1);
    pInjectionPointLayout->addWidget(pLabelInjectionPressureUnit,1,2);
    pInjectionPointLayout->addWidget(pInjectionDiameterLabel,2,0);
    pInjectionPointLayout->addWidget(m_pInjectionDiameterLineEdit,2,1);
    pInjectionPointLayout->addWidget(pLabelInjectionDiameterUnit,2,2);

    QDoubleValidator* pDoubleValidator = new QDoubleValidator(this);
    QLabel* pPermeabilityLabel = new QLabel(tr("Permeability:"));
    QLabel* pCavityHeightLabel = new QLabel(tr("Cavity Height:"));
    QLabel* pPorosityLabel = new QLabel(tr("Porosity:"));
    pPermeabilityLabel->setFixedWidth(nLabelLength);
    pCavityHeightLabel->setFixedWidth(nLabelLength);
    pPorosityLabel->setFixedWidth(nLabelLength);
    m_pPermeabilityLineEdit = new QLineEdit;
    m_pCavityHeightLineEdit = new QLineEdit;
    m_pPorosityLineEdit = new QLineEdit;
    QLabel* pPermeabilityUnit = new QLabel(tr("m<sup>2</sup>"));
    QLabel* pCavityHeightUnit = new QLabel(tr("m"));

    m_pCheckBoxShowPermeabilityGradient = new QCheckBox(tr("show Permeability Gradient"));

    m_pPermeabilityLineEdit->setValidator(pDoubleValidator);
    m_pCavityHeightLineEdit->setValidator(pDoubleValidator);
    m_pPermeabilityLineEdit->setFixedWidth(nLineEditLength);
    m_pCavityHeightLineEdit->setFixedWidth(nLineEditLength);
    m_pPorosityLineEdit->setFixedWidth(nLineEditLength);
    m_pPorosityLineEdit->setValidator(pDoubleValidator);

    pCellSettingsLayout->addWidget(pPermeabilityLabel,0,0);
    pCellSettingsLayout->addWidget(m_pPermeabilityLineEdit,0,1);
    pCellSettingsLayout->addWidget(pPermeabilityUnit,0,2);
    pCellSettingsLayout->addWidget(pCavityHeightLabel,1,0);
    pCellSettingsLayout->addWidget(m_pCavityHeightLineEdit,1,1);
    pCellSettingsLayout->addWidget(pCavityHeightUnit,1,2);
    pCellSettingsLayout->addWidget(pPorosityLabel,2,0);
    pCellSettingsLayout->addWidget(m_pPorosityLineEdit,2,1);
    pCellSettingsLayout->addWidget(m_pCheckBoxShowPermeabilityGradient,3,0,1,2);

    QHBoxLayout* pActionLayout = new QHBoxLayout;
    QPushButton* pButtonSave = new QPushButton(tr("Save"));
    QPushButton* pButtonRefresh = new QPushButton(tr("Refresh"));
    m_pBoxLayout->addLayout(pActionLayout);
    pActionLayout->addWidget(pButtonRefresh);
    pActionLayout->addWidget(pButtonSave);

    m_pBoxLayout->addStretch();

    connect(pButtonSave, SIGNAL(clicked()), this, SLOT(saveNodeSettings()));
    connect(pButtonRefresh, SIGNAL(clicked()), this, SLOT(refreshNodeSettings()));
    connect(m_pCheckBoxShowPermeabilityGradient, SIGNAL(stateChanged(int)), m_pSimulator, SLOT(showPermeabilityGradient(int)));

    pPermeabilityUnit->adjustSize();
    pLabelInjectionPressureUnit->setFixedWidth(pPermeabilityUnit->width());
}




/**
 * This slot should be called whenever the 'reactivate swept nodes' button is clicked.
 * Reactivates all previously swept, but not deleted nodes.
 */
void PreprocessingTab::buttonReactivateSweptNodesClicked()
{
    m_pSimulator->resetSweep();
}







