/* 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 <QClipboard>
#include <QScreen>
#include <QMouseEvent>
#include <QTextDocument>
#include <QTimer>


/////////////////////// pappsomspp includes


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

namespace MsXpS
{
namespace libXpertMassGui
{

TextDetailsWidget::TextDetailsWidget(const QFont &font, QWidget *parent)
  : QWidget(parent)
{
  // Window flags: Make it a frameless, always-on-top tooltip
  setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint |
                 Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus);
  setAttribute(Qt::WA_TranslucentBackground);
  setAttribute(Qt::WA_ShowWithoutActivating);

  // CRITICAL: Make the widget transparent to mouse events!
  // This ensures that when the tooltip pops up under the cursor,
  // the mouse events still pass through to the QCustomPlot underneath.
  // No, no more because we want to allow the user to click the copy
  // push button.
  // setAttribute(Qt::WA_TransparentForMouseEvents, true);

  // Layout
  QVBoxLayout *layout = new QVBoxLayout(this);
  layout->setContentsMargins(0, 0, 0, 0); // No margins, let QTextEdit handle it
  layout->setSpacing(0);

  // The multiline edit widget
  mp_textEdit = new QTextEdit(this);
  mp_textEdit->setReadOnly(true); // Prevent editing, but allow selection
  mp_textEdit->setFrameStyle(QFrame::NoFrame); // Remove default borders
  mp_textEdit->setFrameShape(QFrame::NoFrame);
  mp_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  mp_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  mp_textEdit->viewport()->setAutoFillBackground(false);
  mp_textEdit->setFont(font);
  layout->addWidget(mp_textEdit);

  // The copy-to-clipboard button
  mp_copyButton = new QPushButton(this);
  mp_copyButton->setIcon(QIcon(":/gui/images/svg/copy-to-clipboard-icon.svg"));
  mp_copyButton->setIconSize(QSize(16, 16));
  mp_copyButton->setToolTip("Copy to clipboard");
  mp_copyButton->setFlat(true);
  mp_copyButton->setCursor(Qt::PointingHandCursor);
  mp_copyButton->setFixedSize(28, 28);

  layout->addWidget(mp_copyButton, 0, Qt::AlignRight | Qt::AlignBottom);


  // --- Styling ---
  setStyleSheet(R"(
        TextDetailsWidget {
            background-color: #dcfaff; 
            border: 1px solid #3F3F46;
            border-radius: 6px;
        }
        QTextEdit {
            // background: transparent;
            background-color: #889dda;
            color: #88cad6;
            border: none;
            padding: 0;
            font-size: 13px;
            selection-background-color: #007ACC;
            selection-color: #FFFFFF;
        }
        QPushButton {
            background-color: #889dda;
            border: 1px solid transparent;
            border-radius: 4px;
        }
        QPushButton:hover {
            background-color: #889dda;
            border: 1px solid #555555;
        }
        QPushButton:pressed {
            background-color: #9e88da;
        }
    )");

  // Auto-hide timer
  mp_hideTimer = new QTimer(this);
  mp_hideTimer->setSingleShot(true);
  connect(mp_hideTimer, &QTimer::timeout, this, &TextDetailsWidget::hideWidget);
  connect(mp_copyButton,
          &QPushButton::clicked,
          this,
          &TextDetailsWidget::copyTextToClipboard);

  qApp->installEventFilter(this);
  hide();
}

void
TextDetailsWidget::showText(const QString &text,
                            const QPoint &globalMousePos,
                            bool is_html)
{
  if(is_html)
    mp_textEdit->setHtml(text);
  else
    mp_textEdit->setPlainText(text);

  int targetWidth = 260;
  mp_textEdit->document()->setTextWidth(targetWidth);
  QSizeF doc_size_f = mp_textEdit->document()->size();
  QSize doc_size    = doc_size_f.toSize();

  int margin           = 20; // 10px padding on all sides
  int buttonAreaHeight = 36; // 28px button + 8px spacing

  int totalWidth  = doc_size.width() + margin;
  int totalHeight = doc_size.height() + margin + buttonAreaHeight;

  // Prevent the widget from taking up the entire screen vertically
  int maxHeight =
    QApplication::primaryScreen()->availableGeometry().height() * 0.75;
  if(totalHeight > maxHeight)
    {
      totalHeight = maxHeight;
      mp_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    }
  else
    {
      mp_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    }

  setFixedSize(totalWidth, totalHeight);

  // --- Positioning ---
  QPoint finalPos  = globalMousePos + QPoint(15, 15);
  QRect screenGeom = QApplication::primaryScreen()->availableGeometry();

  if(finalPos.x() + width() > screenGeom.right())
    {
      finalPos.setX(globalMousePos.x() - width() - 15);
    }
  if(finalPos.y() + height() > screenGeom.bottom())
    {
      finalPos.setY(globalMousePos.y() - height() - 15);
    }

  move(finalPos);
  show();
  raise();

  startHideTimer();
}

void
TextDetailsWidget::forcefullyHide()
{
  hideWidget();
}

void
TextDetailsWidget::copyTextToClipboard()
{
  // We copy the plain text so the user doesn't get raw HTML tags in their
  // clipboard
  QApplication::clipboard()->setText(mp_textEdit->toPlainText());

  mp_copyButton->setIcon(QIcon(":/gui/images/svg/black-check-mark-icon.svg"));
  QTimer::singleShot(1000, this, [this]() {
    mp_copyButton->setIcon(
      QIcon(":/gui/images/svg/copy-to-clipboard-icon.svg"));
  });
}

void
TextDetailsWidget::enterEvent(QEnterEvent *event)
{
  // qDebug() << "";

  mp_hideTimer->stop();
  QWidget::enterEvent(event);
}

void
TextDetailsWidget::leaveEvent(QEvent *event)
{
  // qDebug() << "";

  startHideTimer();
  QWidget::leaveEvent(event);
}

void
TextDetailsWidget::startHideTimer()
{
  // qDebug() << "";

  // Right enough time to be able to release the mouse, go on the
  // widget area and click the copy-to-clipboard button.
  mp_hideTimer->start(500); // these are milliseconds
}

void
TextDetailsWidget::hideWidget()
{
  // qDebug() << "";

  hide();
}

bool
TextDetailsWidget::eventFilter(QObject *obj, QEvent *event)
{
  // qDebug() << "";

  if(event->type() == QEvent::MouseButtonPress)
    {
      if(isVisible() && !geometry().contains(QCursor::pos()))
        {
          hideWidget();
        }
    }
  return QWidget::eventFilter(obj, event);
}


} // namespace libXpertMassGui
} // namespace MsXpS
