//=========================================================================
//  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.
//=========================================================================

// local includes
#include "smtk/simulation/ace3p/JobsManifest.h"
#include "smtk/simulation/ace3p/qt/qtJobsModel.h"
#include "smtk/simulation/ace3p/utility/AttributeUtils.h"
#include "smtk/simulation/ace3p/Project.h"

// smtk includes
#include "smtk/project/Project.h"
#include "smtk/attribute/Resource.h"
#include "smtk/attribute/StringItem.h"

// Qt includes
#include <QDebug>
#include <QString>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

qtJobsModel::qtJobsModel(QWidget* parent)
{}

std::string qtJobsModel::col2field(JobsFields col) const
{
  switch(col)
  {
    case JobsFields::JobName:
      return "job_name";
    case JobsFields::AnalysisType:
      return "analysis";
    case JobsFields::Status:
      return "status";
    case JobsFields::StartTime:
      return "submission_time";
    case JobsFields::Notes:
      return "notes";
    case JobsFields::SlurmID:
      return "slurm_id";
    case JobsFields::Processes:
      return "processes";
    case JobsFields::Nodes:
      return "nodes";
    case JobsFields::Machine:
      return "machine" ;
    case JobsFields::RemoteDir:
      return "runtime_job_folder";
    case JobsFields::LocalDir:
      return "local_job_folder";
    case JobsFields::InputDir:
      return "runtime_input_folder";
  }
  return "";
}

QVariant qtJobsModel::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 qtJobsModel::rowCount(const QModelIndex &parent) const
{
  if(parent.isValid())
  {
    return 0;
  }
  if (!m_project)
  {
    return 0;
  }
  return m_project->jobsManifest().size();
}

int qtJobsModel::columnCount(const QModelIndex &parent) const
{
  Q_UNUSED(parent);
  return m_nCols;
}

QVariant qtJobsModel::data(const QModelIndex &index, int role) const
{
  if(!m_project)
    return false;
  // default return value
  QVariant ret = QVariant();

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

  const auto jm = m_project->jobsManifest();

  // check if we are on an analysis
  if(row >= jm.size() || col >= m_nCols)
  {
    return ret;
  }

  // get the data out of the Attribute Resource
  if(role == Qt::DisplayRole || role == Qt::EditRole)
  {
    std::string s;
    m_project->getJobRecordField(row, col2field(JobsFields(col)), s);
    ret = QVariant(tr(s.c_str()));
  }

  if(role == Qt::TextAlignmentRole)
  {
    ret = QVariant(Qt::AlignCenter);
  }

  return ret;
}

bool qtJobsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
  const int row = index.row();
  const int col = index.column();
  if(!m_project)
    return false;
  if(role == Qt::EditRole)
  {
    const int row = index.row();
    const int col = index.column();
    std::string str = value.toString().toStdString();
    m_project->setJobRecordField(row, col2field(JobsFields(col)), str);
    emit dataChanged(index, index);
    return true;
  }
  return false;
}

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

  Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable
                             | Qt::ItemIsEnabled
                             | Qt::ItemIsEditable;
  return defaultFlags;
}

void qtJobsModel::populateJobs(smtk::project::ProjectPtr project)
{
  this->beginResetModel();
  if(!m_project)
  {
    m_project = smtk::static_pointer_cast<smtk::simulation::ace3p::Project>(project);
  }
  this->endResetModel();
}

void qtJobsModel::updateJobs()
{
  // no op
}

}
}
}
