//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#include "ProcessDocsDlg.hpp"

#include <QHash>
#include <QRegExp>
#include <QTreeWidget>
#include <QWidget>

#include "Information.hpp"
#include "ProcessUtils.hpp"

#include <ui_ProcessDocs.h>

namespace mgx
{
  ProcessDocsDialog::ProcessDocsDialog(QWidget* parent) : QDialog(parent)
  {
    ui = new Ui::ProcessDocsDialog;
    ui->setupUi(this);
    findProcesses();
  }
  
  ProcessDocsDialog::~ProcessDocsDialog() 
  {
    if(ui)
      delete ui;
  }
  
  void ProcessDocsDialog::findProcesses()
  {
    QHash<QString, QTreeWidgetItem*> stackFolders, meshFolders, miscFolders;
    QStringList processList = listProcesses();

    for(const QString &text : processList) {
      QString tab, folder, name;
      if(!getProcessText(text, tab, folder, name))
        continue;

      QTreeWidget *tree;
      QHash<QString, QTreeWidgetItem*> *folders;
      if(tab == "Stack") {
        tree = ui->StackTreeWidget;
        folders = &stackFolders;
      } else if(tab == "Mesh") {
        tree = ui->MeshTreeWidget;
        folders = &meshFolders;
      } else if(tab == "Misc") {
        tree = ui->MiscTreeWidget;
        folders = &miscFolders;
      } else {
        Information::out 
            << QString("findProcesses cannot find correct tab (%1) for process").arg(tab) << endl;
        continue;
      }

      ProcessDefinition* def = getProcessDefinition(text);
      if(not def) {
        Information::err << 
           QString("Couldn't find definition of process %1").arg(text) << endl;
        continue;
      }
      QStringList desc;
      // The full name goes in column 2
      desc << name << def->name;

      QTreeWidgetItem* item = new QTreeWidgetItem(QStringList() << name << def->name);
      item->setFlags(Qt::ItemIsEnabled | /*Qt::ItemNeverHasChildren |*/ Qt::ItemIsSelectable);
      item->setToolTip(0, def->description);
      item->setIcon(0, def->icon);
      if(folder.isEmpty())
        tree->addTopLevelItem(item);
      else {
        // getFolder, recursively creates the tree
        QTreeWidgetItem* folderWidget = getFolder(folder, *folders, tree);
        folderWidget->addChild(item);
      }
    }
    ui->StackTreeWidget->sortItems(0, Qt::AscendingOrder);
    ui->StackTreeWidget->resizeColumnToContents(0);
    ui->MeshTreeWidget->sortItems(0, Qt::AscendingOrder);
    ui->MeshTreeWidget->resizeColumnToContents(0);
    ui->MiscTreeWidget->sortItems(0, Qt::AscendingOrder);
    ui->MiscTreeWidget->resizeColumnToContents(0);
  }
  
  void ProcessDocsDialog::on_StackTreeWidget_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*)
  {
    if(item->childCount() == 0) {
      ProcessDefinition* def = getProcessDefinition(item->text(1));
      if(def)
        updateDocView(def);
    }
  }
  
  void ProcessDocsDialog::on_MeshTreeWidget_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*)
  {
    if(item->childCount() == 0) {
      ProcessDefinition* def = getProcessDefinition(item->text(1));
      if(def)
        updateDocView(def);
    }
  }
   
  void ProcessDocsDialog::on_MiscTreeWidget_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*)
  {
    if(item->childCount() == 0) {
      ProcessDefinition* def = getProcessDefinition(item->text(1));
      if(def)
        updateDocView(def);
    }
  }

  void ProcessDocsDialog::updateDocView(ProcessDefinition* def)
  {
    QStringList html;
    QString desc = def->description;
    QString icon_name = QString("icon://%1").arg(def->name);
    icon_name.replace(" ", "_");
    QTextDocument *doc = ui->Doc->document();
    doc->addResource(QTextDocument::ImageResource, QUrl(icon_name), def->icon.pixmap(QSize(64, 64)));
    desc.replace("\n", "<br/>");
    html << QString("<h1><img src=\"%3\"/> %1</h1>").arg(def->name).arg(icon_name)
         << QString("<h2>Description</h2><p>%1</p>").arg(desc);
    if(not def->parmNames.empty()) {
      html << "<h2>Parameters</h2>"
           << "<table width='100%' border=1 cell-spacing='1' style='border-width: 1px;border-style: solid'>";
      for(int i = 0; i < def->parmNames.size(); ++i) {
        html << "<tr><td width='20%'><b>" << def->parmNames[i] << "</b></td>";
        QString desc;
        if(i < def->parmDescs.size())
          desc = def->parmDescs[i].trimmed();
        else
          desc = def->parmNames[i];
        desc.replace("\n", "<br/>");
        html << "<td> " << desc << " </td>";
        html << "</tr>";
      }
      html << "</table></frame><br/><br/>";
    }
  
    ui->Doc->setHtml(html.join("\n"));
  }
  
  void ProcessDocsDialog::on_StackFilter_textChanged(const QString& text)
  {
    filterProcesses(ui->StackTreeWidget, text);
  }
  
  void ProcessDocsDialog::on_MeshFilter_textChanged(const QString& text)
  {
    filterProcesses(ui->MeshTreeWidget, text);
  }

  void ProcessDocsDialog::on_MiscFilter_textChanged(const QString& text)
  {
    filterProcesses(ui->MiscTreeWidget, text);
  }
}
