//                                               -*- C++ -*-
/**
 *  @brief QMdiSubWindow for the results of SobolAnalysis
 *
 *  Copyright 2015-2026 EDF-Phimeca
 *
 *  This library is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "persalys/SobolResultWindow.hxx"

#include "persalys/SobolAnalysis.hxx"
#include "persalys/SensitivityResultWidget.hxx"
#include "persalys/ResizableStackedWidget.hxx"
#include "persalys/QtTools.hxx"
#include "persalys/ExportableTableView.hxx"
#include "persalys/ErrorWidget.hxx"

#include <QGroupBox>
#include <QComboBox>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QSplitter>
#include <QLabel>

using namespace OT;

namespace PERSALYS
{

SobolResultWindow::SobolResultWindow(AnalysisItem * item, QWidget * parent)
  : ResultWindow(item, parent)
  , result_()
{
  const SobolAnalysis * sobolAnalysis = dynamic_cast<const SobolAnalysis*>(item->getAnalysis().getImplementation().get());
  if (!sobolAnalysis)
    throw InvalidArgumentException(HERE) << "SobolResultWindow: the analysis is not a SobolAnalysis";

  result_ = sobolAnalysis->getResult();

  // parameters widget
  setParameters(item->getAnalysis(), tr("Sensitivity analysis parameters"));

  buildInterface();
}


void SobolResultWindow::buildInterface()
{
  QVBoxLayout * widgetLayout = new QVBoxLayout(this);

  widgetLayout->addWidget(new TitleLabel(tr("Sobol indices"), "user_manual/graphical_interface/probabilistic_analysis/user_manual_probabilistic_analysis.html#sobolresult"));

  // get number of outputs
  const UnsignedInteger nbOutputs = result_.getOutputNames().getSize();

  // main splitter
  QSplitter * mainWidget = new QSplitter(Qt::Horizontal);

  // - tab widget
  QTabWidget * tabWidget = new QTabWidget;

  // first tab --------------------------------
  if (result_.getFirstOrderIndices().getSize() == nbOutputs)
  {
    QScrollArea * scrollArea = new QScrollArea;
    scrollArea->setWidgetResizable(true);
    QWidget * widget = new QWidget;
    QVBoxLayout * vbox = new QVBoxLayout(widget);

    QComboBox * outputsListWidget = new QComboBox;
    outputsListWidget->addItems(QtOT::DescriptionToStringList(result_.getOutputNames()));
    vbox->addWidget(outputsListWidget);

    ResizableStackedWidget * stackedWidget = new ResizableStackedWidget;
    connect(outputsListWidget, SIGNAL(currentIndexChanged(int)), stackedWidget, SLOT(setCurrentIndex(int)));

    for (UnsignedInteger i = 0; i < nbOutputs; ++i)
    {
      // get indices confidence interval
      Interval foIndicesInterval;
      if (result_.getFirstOrderIndicesInterval().getSize() == nbOutputs)
        foIndicesInterval = result_.getFirstOrderIndicesInterval()[i];
      Interval toIndicesInterval;
      if (result_.getTotalIndicesInterval().getSize() == nbOutputs)
        toIndicesInterval = result_.getTotalIndicesInterval()[i];

      // build widget
      SensitivityResultWidget * indicesResultWidget = new SensitivityResultWidget(result_.getFirstOrderIndices()[i],
          foIndicesInterval,
          result_.getTotalIndices()[i],
          toIndicesInterval,
          result_.getInputNames(),
          result_.getOutputNames()[i],
          SensitivityResultWidget::Sobol,
          DesignOfExperiment::Type::MC,
          this);
      stackedWidget->addWidget(indicesResultWidget);
    }
    vbox->addWidget(stackedWidget, 1);

    scrollArea->setWidget(widget);
    tabWidget->addTab(scrollArea, tr("Indices"));

    // aggregated tab -----------------------------------------
    if(nbOutputs > 1 && result_.getAggregatedFirstOrderIndices().getSize())
    {
      SensitivityResultWidget * aggregatedIndicesResultWidget = new SensitivityResultWidget(
        result_.getAggregatedFirstOrderIndices(),
        result_.getAggregatedFirstOrderIndicesInterval(),
        result_.getAggregatedTotalIndices(),
        result_.getAggregatedTotalIndicesInterval(),
        result_.getInputNames(),
        result_.getOutputNames().__str__(),
        SensitivityResultWidget::Sobol,
        DesignOfExperiment::Type::MC,
        this);
      tabWidget->addTab(aggregatedIndicesResultWidget, tr("Aggregated Indices"));
    }
    outputsListWidget->setCurrentIndex(0);
  }

  // points tab
  tabWidget->addTab(ExportableTableView::GetSampleTableViewWidget(getItem(), result_.getDesignOfExperiment().getSample()), tr("Values"));

  // stopping criteria
  if (result_.getElapsedTime() > 0. && result_.getCallsNumber())
  {
    QWidget * widget = new QWidget;
    QGridLayout * gbox = new QGridLayout(widget);

    const AnalysisItem * analysisItem = dynamic_cast<AnalysisItem *>(getItem());
    QString warningMsg = analysisItem ? QString::fromStdString(analysisItem->getAnalysis().getWarningMessage()) : QString();
    ErrorWidget * errorWidget = new ErrorWidget(widget);
    if (!warningMsg.isEmpty())
      errorWidget->setMessage(warningMsg, ErrorWidget::Error, false, false);
    else
      errorWidget->hide();
    gbox->addWidget(errorWidget, 0, 0, 1, 2);

    QStringList namesList;
    namesList << tr("Elapsed time")
              << tr("Number of calls")
              << tr("Confidence interval length");

    QStringList valuesList;
    valuesList << QtOT::FormatDuration(result_.getElapsedTime())
               << QString::number(result_.getCallsNumber())
               << QString::number(result_.getConfidenceIntervalLength());

    ParametersWidget * parametersWidget = new ParametersWidget(tr("Stopping criteria"), namesList, valuesList, true, true);
    gbox->addWidget(parametersWidget, 1, 0);
    gbox->setColumnStretch(1, 1);
    gbox->setRowStretch(2, 1);
    tabWidget->addTab(widget, tr("Stopping criteria"));
  }

  // third tab ----------------------------------------------
  if (parametersWidget_)
    tabWidget->addTab(parametersWidget_, tr("Parameters"));

  // tab : model description --------------------------------
  if (modelDescriptionWidget_)
    tabWidget->addTab(modelDescriptionWidget_, tr("Model"));

  // set widgets
  mainWidget->addWidget(tabWidget);
  mainWidget->setStretchFactor(1, 10);

  widgetLayout->addWidget(mainWidget, 1);
}
}
