//=========================================================================
//  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 "smtk/simulation/ace3p/qt/qtNerscFileItem.h"

// Plugin includes
#include "smtk/newt/qtNewtFileBrowserDialog.h"
#include "smtk/newt/qtNewtInterface.h"

// SMTK includes
#include "smtk/attribute/Item.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/extension/qt/qtBaseAttributeView.h"
#include "smtk/extension/qt/qtUIManager.h"

#include <QDebug>
#include <QFrame>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QString>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

class qtNerscFileItem::Internal
{
public:
  smtk::attribute::StringItemPtr m_item;

  QLineEdit* m_lineEdit = nullptr;
  newt::qtNewtInterface* m_newt = newt::qtNewtInterface::instance();
};

smtk::extension::qtItem* qtNerscFileItem::createItemWidget(
  const smtk::extension::qtAttributeItemInfo& info)
{
  return new qtNerscFileItem(info);
}

qtNerscFileItem::qtNerscFileItem(const smtk::extension::qtAttributeItemInfo& info)
  : qtItem(info)
{
  this->setObjectName("NERSC File Item");
  m_internal = new qtNerscFileItem::Internal;
  m_internal->m_item = info.itemAs<smtk::attribute::StringItem>();
  m_internal->m_lineEdit = new QLineEdit(m_widget);
  this->createWidget();
}

qtNerscFileItem::~qtNerscFileItem()
{
  delete m_internal;
}

void qtNerscFileItem::clearChildWidgets()
{
  m_internal->m_lineEdit->clear();
}

void qtNerscFileItem::createWidget()
{
  smtk::attribute::ItemPtr item = m_itemInfo.item();
  auto iview = m_itemInfo.baseView();
  if (iview && !iview->displayItem(item))
  {
    return;
  }

  this->clearChildWidgets();
  this->updateUI();
}

void qtNerscFileItem::setBackground()
{
  if (m_internal->m_item->isValid() && !m_internal->m_item->value().empty())
  {
    this->uiManager()->setWidgetColorToNormal(m_internal->m_lineEdit);
  }
  else
  {
    this->uiManager()->setWidgetColorToInvalid(m_internal->m_lineEdit);
  }
}

void qtNerscFileItem::updateUI()
{
  auto item = m_itemInfo.item();
  auto iview = m_itemInfo.baseView();
  if (iview && !iview->displayItem(item))
  {
    return;
  }

  if (m_widget)
  {
    delete m_widget;
  }

  m_widget = new QFrame(m_itemInfo.parentWidget());
  QHBoxLayout* layout = new QHBoxLayout(m_widget);
  layout->setMargin(0);

  if (m_internal->m_item == nullptr)
  {
    QLabel* label = new QLabel(item->label().c_str(), m_widget);
    layout->addWidget(label);
    QString text("Invalid NERSCDIRECTORY ItemView NOT assigned to StringItem");
    QLabel* msg = new QLabel(text, m_widget);
    layout->addWidget(msg);
    return;
  }

  QLabel* label = new QLabel(item->label().c_str(), m_widget);
  if (iview)
  {
    // This logic copied from FileItem
    const int padding = 6;
    label->setFixedWidth(iview->fixedLabelWidth() - padding);
  }
  label->setWordWrap(true);
  label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
  layout->addWidget(label);

  m_internal->m_lineEdit = new QLineEdit(m_widget);
  layout->addWidget(m_internal->m_lineEdit);
  QPushButton* browseButton = new QPushButton("Browse", m_widget);
  layout->addWidget(browseButton);

  QObject::connect(
    m_internal->m_lineEdit, &QLineEdit::editingFinished, this, &qtNerscFileItem::onEditingFinished);
  QObject::connect(browseButton, &QPushButton::clicked, this, &qtNerscFileItem::onBrowse);

  if (m_internal->m_item->isSet())
  {
    m_internal->m_lineEdit->setText(m_internal->m_item->value().c_str());
  }
  this->setBackground();
}

void qtNerscFileItem::onBrowse()
{
  // First check if user is signed in to NERSC
  if (!m_internal->m_newt->isLoggedIn())
  {
    QMessageBox::information(
      this->parentWidget(), "Not Signed in", "You must first log into NERSC from the application.");
    return;
  }

  // Instantiate browser
  newt::qtNewtFileBrowserDialog dialog(this->parentWidget());
  QObject::connect(
    &dialog, &newt::qtNewtFileBrowserDialog::applyPath, this, &qtNerscFileItem::onDialogApply);
  dialog.exec();
}

void qtNerscFileItem::onDialogApply(const QString& path)
{
  if (m_internal->m_item == nullptr)
  {
    return;
  }

  if (path.toStdString() == m_internal->m_item->value())
  {
    return;
  }

  bool isChanged = m_internal->m_item->setValue(path.toStdString());
  if (!isChanged)
  {
    qWarning() << "Failed to set NERSC Directory (path) to" << path;
    return;
  }

  m_internal->m_lineEdit->setText(path);
  this->setBackground();
  emit this->modified();
}

void qtNerscFileItem::onEditingFinished()
{
  if (m_internal->m_item == nullptr)
  {
    return;
  }

  auto inputString = m_internal->m_lineEdit->text().toStdString();
  if (m_internal->m_item->isSet())
  {
    if (inputString == m_internal->m_item->value())
    {
      return;
    }
  }
  else if (inputString.empty())
  {
    return;
  }

  bool isChanged = m_internal->m_item->setValue(inputString);
  if (!isChanged)
  {
    qWarning() << "Failed to set NERSC Directory (path) to" << inputString.c_str();
  }

  this->setBackground();
  emit this->modified();
}
} // namespace ace3p
} // namespace simulation
} // namespace smtk
