//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "qtAnalysisModel.h"
#include "qtProjectRuntime.h"

#include "smtk/attribute/Resource.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/project/Project.h"
#include "smtk/simulation/ace3p/utility/AttributeUtils.h"

#include <QDebug>
#include <QString>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

qtAnalysisModel::qtAnalysisModel(QWidget* parent)
  : m_project(nullptr)
{
}

QVariant qtAnalysisModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (role != Qt::DisplayRole)
    return QVariant();

  if (orientation == Qt::Horizontal && section < m_nCols)
    return m_headers[section];
  else
    return QStringLiteral("%1").arg(section);
}

int qtAnalysisModel::rowCount(const QModelIndex& parent) const
{
  if (parent.isValid())
  {
    return 0;
  }
  return m_nRows;
}
int qtAnalysisModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return m_nCols;
}

QVariant qtAnalysisModel::data(const QModelIndex& index, int role) const
{
  // default return value
  QVariant ret = QVariant();

  const int row = index.row();
  const int col = index.column();

  // check if we are on an analysis
  if (row >= m_analyses.size())
  {
    return ret;
  }
  auto analysis = smtk::dynamic_pointer_cast<smtk::attribute::Resource>(m_analyses[row]);

  // get the data out of the Attribute Resource
  if (role == Qt::DisplayRole || role == Qt::EditRole)
  {
    smtk::simulation::ace3p::AttributeUtils attUtils;
    auto analysisAtt = attUtils.getAnalysisAtt(analysis);
    assert(analysisAtt != nullptr);
    smtk::attribute::ConstStringItemPtr analysisItem = analysisAtt->findString("Analysis");
    switch (col)
    {
      case 0: // name
        ret = QVariant(tr(analysis->name().c_str()));
        break;
      case 1: // analysis code
        if (analysisItem->isSet())
          ret = QVariant(tr(analysisItem->value().c_str()));
        else
          ret = QVariant(tr("(not set)"));
        break;
      case 2: // description
        ret = QVariant(tr(m_descriptions[row].c_str()));
        break;
      case 3: // uuid
        ret = QVariant(tr(analysis->id().toString().c_str()));
        break;
    }
  }

  if (role == Qt::TextAlignmentRole)
  {
    ret = QVariant(m_textAlignmentRoles[col]);
  }

  return ret;
}

bool qtAnalysisModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
  const int row = index.row();
  const int col = index.column();

  if (role == Qt::EditRole)
  {
    std::string str = value.toString().toStdString();
    if (col == 2)
    {

      m_descriptions[row] = str;
      emit dataChanged(index, index);
      return true;
    }
    if (col == 0)
    {
      m_analyses[row]->setName(str);
      emit dataChanged(index, index);
      return true;
    }
  }
  return false;
}

Qt::ItemFlags qtAnalysisModel::flags(const QModelIndex& index) const
{
  const int col = index.column();

  Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
  if (col == 0 || col == 2)
  {
    defaultFlags |= Qt::ItemIsEditable;
  }
  return defaultFlags;
}

////////////////////////////////////////////////////////////////////////////////
void qtAnalysisModel::populateAnalyses(smtk::project::ProjectPtr project)
{
  if (!m_project)
  {
    m_project = project;
  }
  updateAnalyses();
}

void qtAnalysisModel::updateAnalyses()
{
  auto analyses = m_project->resources().find("smtk::attribute::Resource");
  m_analyses.resize(analyses.size());
  m_analyses.assign(analyses.begin(), analyses.end());
  m_descriptions.resize(analyses.size(), m_defaultDescp);

  int nRowsOld = m_nRows;
  m_nRows = m_analyses.size();
  if (m_nRows != nRowsOld)
  {
    QModelIndex topLeft = this->createIndex(0, 0);
    emit beginInsertRows(topLeft, nRowsOld, m_nRows - 1);
    emit endInsertRows();
    emit layoutAboutToBeChanged();
    emit layoutChanged();
  }
}

void qtAnalysisModel::onAnalysisSelected(const QModelIndex& index)
{
  if (index.isValid())
    emit selectedAnalysis(m_analyses[index.row()]);
  else
    emit selectedAnalysis(nullptr);
}

void qtAnalysisModel::analysisSelectionChanged(
  const QItemSelection& selected,
  const QItemSelection& deselected)
{
  if (selected.size())
    emit selectedAnalysis(m_analyses[selected.indexes()[0].row()]);
  else
    emit selectedAnalysis(nullptr);
}

} // namespace ace3p
} // namespace simulation
} // namespace smtk
