#include "newnotebookdialog.h"

#include <QLineEdit>

#include "../widgetsfactory.h"
#include "configmgr.h"
#include "exception.h"
#include "notebook/inotebookfactory.h"
#include "notebook/notebookparameters.h"
#include "notebookinfowidget.h"
#include "notebookmgr.h"
#include "vnotex.h"
#include <utils/pathutils.h>
#include <utils/utils.h>

using namespace vnotex;

NewNotebookDialog::NewNotebookDialog(QWidget *p_parent) : ScrollDialog(p_parent) {
  setupUI();

  m_infoWidget->getNameLineEdit()->setFocus();
}

void NewNotebookDialog::setupUI() {
  setupNotebookInfoWidget(this);
  setCentralWidget(m_infoWidget);

  setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);

  setWindowTitle(tr("New Notebook"));
}

void NewNotebookDialog::setupNotebookInfoWidget(QWidget *p_parent) {
  m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::Create, p_parent);
  connect(m_infoWidget, &NotebookInfoWidget::rootFolderEdited, this,
          &NewNotebookDialog::handleRootFolderPathChanged);

  {
    auto whatsThis = tr("<br/>Both absolute and relative paths are supported. ~ and environment "
                        "variable are not supported now.");
    auto rootFolderEdit = m_infoWidget->getRootFolderPathLineEdit();
    rootFolderEdit->setWhatsThis(rootFolderEdit->whatsThis() + whatsThis);
  }
}

bool NewNotebookDialog::validateInputs() {
  bool valid = true;
  QString msg;

  valid = valid && validateNameInput(msg);
  valid = valid && validateRootFolderInput(msg);

  setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info
                                : ScrollDialog::InformationLevel::Error);
  return valid;
}

bool NewNotebookDialog::validateNameInput(QString &p_msg) {
  if (m_infoWidget->getName().isEmpty()) {
    Utils::appendMsg(p_msg, tr("Please specify a name for the notebook."));
    return false;
  }

  return true;
}

bool NewNotebookDialog::validateRootFolderInput(QString &p_msg) {
  auto rootFolderPath = m_infoWidget->getRootFolderPath();
  if (!PathUtils::isLegalPath(rootFolderPath)) {
    Utils::appendMsg(p_msg, tr("Please specify a valid root folder for the notebook."));
    return false;
  }

  {
    QFileInfo finfo(rootFolderPath);
    if (finfo.exists()) {
      if (finfo.isDir()) {
        if (!QDir(rootFolderPath).isEmpty()) {
          Utils::appendMsg(p_msg,
                           tr("Root folder of the notebook must be empty. "
                              "If you want to import existing data, please try other operations."));
          return false;
        }
      } else {
        Utils::appendMsg(p_msg, tr("Root folder should be a directory."));
        return false;
      }
    }
  }

  // Check if there already exists one notebook with the same root folder.
  {
    auto &notebookMgr = VNoteX::getInst().getNotebookMgr();
    auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath);
    if (notebook) {
      Utils::appendMsg(p_msg, tr("There already exists a notebook (%1) with the same root folder.")
                                  .arg(notebook->getName()));
      return false;
    }
  }

  return true;
}

void NewNotebookDialog::acceptedButtonClicked() {
  if (validateInputs() && newNotebook()) {
    accept();
  }
}

bool NewNotebookDialog::newNotebook() {
  auto &notebookMgr = VNoteX::getInst().getNotebookMgr();
  auto paras = NotebookParameters::createNotebookParameters(
      notebookMgr, m_infoWidget->getType(), m_infoWidget->getName(), m_infoWidget->getDescription(),
      m_infoWidget->getRootFolderPath(), m_infoWidget->getIcon(), Notebook::c_defaultImageFolder,
      Notebook::c_defaultAttachmentFolder, QDateTime::currentDateTimeUtc(),
      m_infoWidget->getBackend(), m_infoWidget->getVersionController(),
      m_infoWidget->getConfigMgr());
  try {
    notebookMgr.newNotebook(paras);
  } catch (Exception &p_e) {
    QString msg = tr("Failed to create notebook in (%1) (%2).")
                      .arg(m_infoWidget->getRootFolderPath(), p_e.what());
    qCritical() << msg;
    setInformationText(msg, ScrollDialog::InformationLevel::Error);
    return false;
  }

  return true;
}

void NewNotebookDialog::handleRootFolderPathChanged() {
  auto nameEdit = m_infoWidget->getNameLineEdit();
  if (nameEdit->text().isEmpty()) {
    nameEdit->setText(PathUtils::dirName(m_infoWidget->getRootFolderPath()));
  }
}
