/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright 2009--2026 by Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */


/////////////////////// Qt includes
#include <QApplication>
#include <QListWidget>
#include <QDebug>
#include <QMouseEvent>
#include <QMenu>
#include <QAction>
#include <QClipboard>


///////////////////////////// Local includes
#include "MsXpS/libXpertMassGui/ScriptingHistoryListWidget.hpp"

namespace MsXpS
{
namespace libXpertMassGui
{

ScriptingHistoryListWidget::ScriptingHistoryListWidget(QWidget *parent)
  : QListWidget(parent)
{
  setContextMenuPolicy(Qt::ActionsContextMenu);

  QString shortcut;
  QKeySequence keySequence;

  shortcut    = "Ctrl+O, Ctrl+S";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  QAction *action = new QAction("Overwrite item(s) to Script input", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::overwriteSelectedItemsText);
  insertAction(Q_NULLPTR, action);

  shortcut    = "Ctrl+I, Ctrl+S";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Insert item(s) to Script input", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::insertSelectedItemsText);
  insertAction(Q_NULLPTR, action);

  action = new QAction("", this);
  action->setSeparator(true);

  shortcut    = "Ctrl+C, Ctrl+S";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Copy selected item(s) to clipboard", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::copySelectedItemsTextToClipboard);
  insertAction(Q_NULLPTR, action);

  action = new QAction("", this);
  action->setSeparator(true);

  shortcut    = "Ctrl+R, Ctrl+S";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Remove Selected", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::removeSelected);
  insertAction(Q_NULLPTR, action);

  action = new QAction("", this);
  action->setSeparator(true);

  shortcut    = "Ctrl+R, Ctrl+D";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Remove Duplicates when contiguous", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::removeDuplicates);
  insertAction(Q_NULLPTR, action);

  action = new QAction("", this);
  action->setSeparator(true);

  shortcut    = "Ctrl+S, Ctrl+A";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Show All", this);
  action->setShortcut(keySequence);
  connect(
    action, &QAction::triggered, this, &ScriptingHistoryListWidget::showAll);
  insertAction(Q_NULLPTR, action);

  shortcut    = "Ctrl+T, Ctrl+S";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Toggle Selection", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::toggleSelection);
  insertAction(Q_NULLPTR, action);

  shortcut    = "Ctrl+H, Ctrl+S";
  keySequence = QKeySequence::fromString(shortcut, QKeySequence::PortableText);
  action      = new QAction("Hide Selected", this);
  action->setShortcut(keySequence);
  connect(action,
          &QAction::triggered,
          this,
          &ScriptingHistoryListWidget::hideSelected);
  insertAction(Q_NULLPTR, action);
}

ScriptingHistoryListWidget::~ScriptingHistoryListWidget()
{
}

void
ScriptingHistoryListWidget::keyPressEvent(QKeyEvent *event)
{
  QListWidget::keyPressEvent(event);
  event->ignore();
}

void
ScriptingHistoryListWidget::showAll()
{
  for(int iter = 0; iter < count(); ++iter)
    setRowHidden(iter, false);
}

void
ScriptingHistoryListWidget::toggleSelection()
{
  for(int iter = 0; iter < count(); ++iter)
    {
      bool isSelected = item(iter)->isSelected();
      item(iter)->setSelected(!isSelected);
    }
}

void
ScriptingHistoryListWidget::hideSelected()
{
  for(int iter = 0; iter < count(); ++iter)
    {
      if(item(iter)->isSelected())
        setRowHidden(iter, true);
    }
}

void
ScriptingHistoryListWidget::removeSelected()
{
  QList<QListWidgetItem *> list = selectedItems();

  for(int iter = 0; iter < list.size(); ++iter)
    {

      // Cannot understand why simply delete list.at(iter) does not work.
      // delete(list.at());

      QListWidgetItem *curItem = takeItem(row(list.at(iter)));
      delete curItem;
    }
}

void
ScriptingHistoryListWidget::removeDuplicates()
{
  qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  if(count() < 2)
    return;

  QList<int> removeIndices;
  QList<QListWidgetItem *> removeItems;

  QString prevText = item(0)->text();

  for(int iter = 1; iter < count(); ++iter)
    {
      QListWidgetItem *curItem = item(iter);
      QString curText          = curItem->text();

      if(curText == prevText)
        {
          removeIndices.append(iter);
          removeItems.append(curItem);
        }

      prevText = curText;
    }

  // Now remove all the duplicate items.

  for(int iter = 0; iter < removeItems.size(); ++iter)
    {

      // Cannot understand why simply delete list.at(iter) does not work.
      // delete(list.at());

      QListWidgetItem *curItem = takeItem(row(removeItems.at(iter)));
      delete curItem;
    }
}

void
ScriptingHistoryListWidget::overwriteSelectedItemsText()
{
  emit setSelectedItemsTextToScriptInput(selectedItemsText(),
                                         true /* overwrite */);
}

void
ScriptingHistoryListWidget::insertSelectedItemsText()
{
  emit setSelectedItemsTextToScriptInput(selectedItemsText(),
                                         false /* overwrite */);
}

void
ScriptingHistoryListWidget::deselectAll()
{
  for(int iter = 0; iter < count(); ++iter)
    {
      if(item(iter)->isSelected())
        item(iter)->setSelected(false);
    }
}

void
ScriptingHistoryListWidget::copySelectedItemsTextToClipboard()
{
  QString text = selectedItemsText();

  if(!text.isEmpty())
    {
      QClipboard *clipboard = QApplication::clipboard();

      clipboard->setText(text, QClipboard::Clipboard);

      if(clipboard->supportsSelection())
        clipboard->setText(text, QClipboard::Selection);
    }
}

QString
ScriptingHistoryListWidget::selectedItemsText()
{
#if 0
			// In fact, we want to get the list of selected items. But beware, the
			// list is ordered in the selection chronological order, which is not what
			// we want.

			QList<QListWidgetItem *> selItemList = selectedItems();

			QString scriptContents;

			for(int iter = 0; iter < selItemList.size(); ++iter)
			{
				scriptContents.append(selItemList.at(iter)->text() + "\n");
			}

			return scriptContents;
#endif

  QString scriptContents;
  int itemCount = count();

  for(int iter = 0; iter < itemCount; ++iter)
    {
      QListWidgetItem *curItem = item(iter);
      if(curItem->isSelected())
        {
          QString itemText = item(iter)->text();

          // We do not want to append a newline if that is the
          // last item of the list

          if(iter == itemCount - 1)
            scriptContents.append(itemText);
          else
            scriptContents.append(itemText + "\n");
        }
    }
  return scriptContents;
}

void
ScriptingHistoryListWidget::selectItemIndices(int startIndex, int endIndex)
{

  // First of all, deselect all:
  deselectAll();

  // And now start making the selection work.
  int itemCount = count();

  int localStart = startIndex;
  int localEnd   = endIndex;

  if(startIndex > endIndex)
    {
      localStart = endIndex;
      localEnd   = startIndex;
    }

  if(localStart < 0)
    localStart = 0;

  if(localEnd >= itemCount)
    localEnd = itemCount - 1;

  for(int iter = localStart; iter <= localEnd; ++iter)
    {
      QListWidgetItem *curItem = item(iter);
      curItem->setSelected(true);
    }
}

} // namespace libXpertMassGui
} // namespace MsXpS
