// SPDX-FileCopyrightText: 2021 Ernie Pasveer <epasveer@att.net>
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "SeerThreadIdsBrowserWidget.h"
#include "SeerUtl.h"
#include <QtWidgets/QTreeWidget>
#include <QtWidgets/QTreeWidgetItemIterator>
#include <QtWidgets/QApplication>
#include <QtGui/QFont>
#include <QtCore/QDebug>

SeerThreadIdsBrowserWidget::SeerThreadIdsBrowserWidget (QWidget* parent) : QWidget(parent) {

    // Construct the UI.
    setupUi(this);

    // Setup the widgets
    idsTreeWidget->setSortingEnabled(false);
    idsTreeWidget->resizeColumnToContents(0); // state
    idsTreeWidget->resizeColumnToContents(1); // id

    idsTreeWidget->clear();

    // Connect things.
    QObject::connect(idsTreeWidget,             &QTreeWidget::itemClicked,          this, &SeerThreadIdsBrowserWidget::handleItemClicked);
    QObject::connect(gdbNextToolButton,         &QToolButton::clicked,              this, &SeerThreadIdsBrowserWidget::handleGdbNextToolButton);
    QObject::connect(gdbStepToolButton,         &QToolButton::clicked,              this, &SeerThreadIdsBrowserWidget::handleGdbStepToolButton);
    QObject::connect(gdbFinishToolButton,       &QToolButton::clicked,              this, &SeerThreadIdsBrowserWidget::handleGdbFinishToolButton);
    QObject::connect(gdbContinueToolButton,     &QToolButton::clicked,              this, &SeerThreadIdsBrowserWidget::handleGdbContinueToolButton);
    QObject::connect(gdbInterruptToolButton,    &QToolButton::clicked,              this, &SeerThreadIdsBrowserWidget::handleGdbInterruptToolButton);
}

SeerThreadIdsBrowserWidget::~SeerThreadIdsBrowserWidget () {
}

void SeerThreadIdsBrowserWidget::handleText (const QString& text) {

    // Don't do any work if the widget is hidden.
    if (isHidden()) {
        return;
    }

    QApplication::setOverrideCursor(Qt::BusyCursor);

    if (text.startsWith("^done,thread-ids={")) {

        QString newtext = Seer::filterEscapes(text); // Filter escaped characters.

        // ^done,thread-ids={
        //        thread-id=\"1\",
        //        thread-id=\"2\"
        //    },
        //    current-thread-id=\"1\",
        //    number-of-threads=\"2\"

        idsTreeWidget->clear();

        QString threadids_text       = Seer::parseFirst(newtext,   "thread-ids=",        '{', '}', false);
        QStringList threadids_list   = Seer::parse(threadids_text, "thread-id=",         '"', '"', false);
        QString currentthreadid_text = Seer::parseFirst(newtext,   "current-thread-id=", '"', '"', false);

        // Add the thread-ids.
        for ( const auto& threadid_text : threadids_list  ) {

            //qDebug() << threadid_text;

            // Construct the item
            QTreeWidgetItem* item = new QTreeWidgetItem;

            if (threadid_text == currentthreadid_text) {
                item->setText(0, "*");
            }else{
                item->setText(0, " ");
            }

            item->setText(1, threadid_text);

            // Set the text to bold if the ID is the same as the CURRENT ID.
            QFont fnormal = item->font(0); fnormal.setBold(false);
            QFont fbold   = item->font(0); fbold.setBold(true);

            if (threadid_text == currentthreadid_text) {
                item->setFont(0, fbold);
                item->setFont(1, fbold);
            }else{
                item->setFont(0, fnormal);
                item->setFont(1, fnormal);
            }

            // Add the frame to the tree.
            idsTreeWidget->addTopLevelItem(item);
        }

        // Clear the selection and select the one for the current thread-id.
        idsTreeWidget->clearSelection();

        QList<QTreeWidgetItem*> matches = idsTreeWidget->findItems(currentthreadid_text, Qt::MatchExactly, 1);
        if (matches.size() > 0) {
            idsTreeWidget->setCurrentItem(matches.first());
        }

    }else{
        // Ignore others.
    }

    idsTreeWidget->resizeColumnToContents(0);
    idsTreeWidget->resizeColumnToContents(1);

    QApplication::restoreOverrideCursor();
}

void SeerThreadIdsBrowserWidget::handleStoppingPointReached () {

    refresh();
}

void SeerThreadIdsBrowserWidget::handleSessionTerminated () {

    // Delete previous contents.
    idsTreeWidget->clear();
}

void SeerThreadIdsBrowserWidget::handleItemClicked (QTreeWidgetItem* item, int column) {

    Q_UNUSED(column);

    emit selectedThread(item->text(1).toInt());
}

void SeerThreadIdsBrowserWidget::refresh () {

    // Don't do any work if the widget is hidden.
    if (isHidden()) {
        return;
    }

    emit refreshThreadIds();
}

void SeerThreadIdsBrowserWidget::handleGdbNextToolButton () {

    QList<QTreeWidgetItem*> items = idsTreeWidget->selectedItems();

    QList<QTreeWidgetItem*>::iterator i;

    for (i = items.begin(); i != items.end(); ++i) {

        int threadid = (*i)->text(1).toInt();

        emit nextThreadId(threadid);
    }
}

void SeerThreadIdsBrowserWidget::handleGdbStepToolButton () {

    QList<QTreeWidgetItem*> items = idsTreeWidget->selectedItems();

    QList<QTreeWidgetItem*>::iterator i;

    for (i = items.begin(); i != items.end(); ++i) {

        int threadid = (*i)->text(1).toInt();

        emit stepThreadId(threadid);
    }
}

void SeerThreadIdsBrowserWidget::handleGdbFinishToolButton () {

    QList<QTreeWidgetItem*> items = idsTreeWidget->selectedItems();

    QList<QTreeWidgetItem*>::iterator i;

    for (i = items.begin(); i != items.end(); ++i) {

        int threadid = (*i)->text(1).toInt();

        emit finishThreadId(threadid);
    }
}

void SeerThreadIdsBrowserWidget::handleGdbContinueToolButton () {

    QList<QTreeWidgetItem*> items = idsTreeWidget->selectedItems();

    QList<QTreeWidgetItem*>::iterator i;

    for (i = items.begin(); i != items.end(); ++i) {

        int threadid = (*i)->text(1).toInt();

        emit continueThreadId(threadid);
    }
}

void SeerThreadIdsBrowserWidget::handleGdbInterruptToolButton () {

    QList<QTreeWidgetItem*> items = idsTreeWidget->selectedItems();

    QList<QTreeWidgetItem*>::iterator i;

    for (i = items.begin(); i != items.end(); ++i) {

        int threadid = (*i)->text(1).toInt();

        emit interruptThreadId(threadid);
    }
}

void SeerThreadIdsBrowserWidget::showEvent (QShowEvent* event) {

    QWidget::showEvent(event);

    refresh();
}

