/*
  SPDX-FileCopyrightText: 2025-2026 Laurent Montel <montel@kde.org>

  SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "textautogeneratehistorylistviewdelegate.h"
#include "core/models/textautogeneratechatsmodel.h"
#include <QAbstractItemView>
#include <QApplication>
#include <QDateTime>
#include <QHelpEvent>
#include <QLineEdit>
#include <QPainter>
#include <QToolTip>

using namespace TextAutoGenerateText;
using namespace Qt::Literals::StringLiterals;
TextAutoGenerateHistoryListViewDelegate::TextAutoGenerateHistoryListViewDelegate(QObject *parent)
    : QItemDelegate{parent}
{
}

TextAutoGenerateHistoryListViewDelegate::~TextAutoGenerateHistoryListViewDelegate() = default;

void TextAutoGenerateHistoryListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (!index.isValid()) {
        return;
    }

    const TextAutoGenerateHistoryListViewDelegate::Layout layout = doLayout(option, index);
    if (layout.isHeader) {
        QItemDelegate::paint(painter, option, index);
        return;
    }

    QStyleOptionViewItem opt(option);
    opt.showDecorationSelected = true;
    QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);

    painter->save();

    // Set the painter font
    painter->setFont(option.font);

    painter->setPen(option.palette.text().color());

    const QRect displayRect = layout.textRect;

    const bool hasPendingMessageTyped = index.data(TextAutoGenerateChatsModel::HasPendingMessageTyped).toBool();
    if (hasPendingMessageTyped) {
        QFont font = opt.font;
        font.setItalic(true);
        opt.font = font;
    }

    drawDisplay(painter, opt, displayRect, layout.title); // this takes care of eliding if the text is too long
    painter->restore();
    drawInProgressIndicator(painter, index, option, layout);
}

QSize TextAutoGenerateHistoryListViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    const QSize defaultSize = QItemDelegate::sizeHint(option, index);
    return defaultSize + QSize(0, 10);
}

void TextAutoGenerateHistoryListViewDelegate::drawInProgressIndicator(QPainter *painter,
                                                                      const QModelIndex &index,
                                                                      [[maybe_unused]] const QStyleOptionViewItem &option,
                                                                      const Layout &layout) const
{
    auto it = std::find_if(mIndexScaleAndOpacitiesList.cbegin(),
                           mIndexScaleAndOpacitiesList.cend(),
                           [index](const TextAutoGenerateDelegateUtils::IndexScaleAndOpacities &key) {
                               return key.index.data(TextAutoGenerateChatsModel::Identifier) == index.data(TextAutoGenerateChatsModel::Identifier);
                           });
    if (it == mIndexScaleAndOpacitiesList.cend()) {
        return;
    }
    const auto scaleAndOpacities = (*it).scaleAndOpacities;
    painter->save();
    painter->setRenderHint(QPainter::Antialiasing);

    const int dotSize = 5;
    const int spacing = TextAutoGenerateDelegateUtils::iconSpacing();

    for (int i = 0; i < scaleAndOpacities.count(); ++i) {
        const TextAutoGenerateText::TextAutoGenerateMessageWaitingAnswerAnimation::ScaleAndOpacity value = scaleAndOpacities.value(i);
        painter->setOpacity(value.opacity);
        painter->save();
        painter->translate(layout.inProgressRect.x() + spacing + i * (dotSize + spacing), layout.inProgressRect.top() + layout.inProgressRect.height() / 2);
        painter->rotate(45);
        painter->scale(value.scale, value.scale);
        painter->setBrush(Qt::black);
        painter->drawEllipse(-dotSize / 2, -dotSize / 2, dotSize, dotSize);
        // painter->fillRect(layout.inProgressRect, Qt::red);
        painter->restore();
    }
    painter->restore();
}

TextAutoGenerateHistoryListViewDelegate::Layout TextAutoGenerateHistoryListViewDelegate::doLayout([[maybe_unused]] const QStyleOptionViewItem &option,
                                                                                                  const QModelIndex &index) const
{
    TextAutoGenerateHistoryListViewDelegate::Layout layout;
    layout.isHeader = !index.parent().isValid();
    layout.title = index.data(TextAutoGenerateChatsModel::Title).toString();

    layout.textRect = QRect(option.rect.topLeft().x(), option.rect.top(), option.rect.width(), option.rect.height());
    const QSize progressIndicatorSize = TextAutoGenerateDelegateUtils::progressIndicatorSize();
    layout.inProgressRect =
        QRect(layout.textRect.topRight().x() - progressIndicatorSize.width(), layout.textRect.top(), progressIndicatorSize.width(), layout.textRect.height());
    return layout;
}

bool TextAutoGenerateHistoryListViewDelegate::helpEvent(QHelpEvent *helpEvent,
                                                        QAbstractItemView *view,
                                                        [[maybe_unused]] const QStyleOptionViewItem &option,
                                                        const QModelIndex &index)
{
    if (!index.isValid()) {
        return false;
    }
    if (helpEvent->type() == QEvent::ToolTip) {
        const QLocale locale;
        const QString toolTip = u"%1 (%2)"_s.arg(index.data(TextAutoGenerateChatsModel::Title).toString(),
                                                 locale.toString(QDateTime::fromSecsSinceEpoch(index.data(TextAutoGenerateChatsModel::DateTime).toInt())));
        QToolTip::showText(helpEvent->globalPos(), toolTip, view);
        return true;
    }
    return false;
}

QWidget *TextAutoGenerateHistoryListViewDelegate::createEditor(QWidget *parent,
                                                               [[maybe_unused]] const QStyleOptionViewItem &option,
                                                               [[maybe_unused]] const QModelIndex &index) const
{
    auto editor = new QLineEdit(parent);
    return editor;
}

void TextAutoGenerateHistoryListViewDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor);
    if (lineEdit) {
        const QString text = index.data(TextAutoGenerateChatsModel::Title).toString();
        lineEdit->setText(text);
    }
}

void TextAutoGenerateHistoryListViewDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor);
    if (lineEdit) {
        model->setData(index, lineEdit->text(), TextAutoGenerateChatsModel::Title);
    }
}

void TextAutoGenerateHistoryListViewDelegate::updateEditorGeometry(QWidget *editor,
                                                                   const QStyleOptionViewItem &option,
                                                                   [[maybe_unused]] const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

void TextAutoGenerateHistoryListViewDelegate::needUpdateWaitingAnswerAnimation(
    const QPersistentModelIndex &index,
    const QList<TextAutoGenerateMessageWaitingAnswerAnimation::ScaleAndOpacity> &scaleAndOpacities)
{
    removeNeedUpdateWaitingAnswerAnimation(index);
    const TextAutoGenerateDelegateUtils::IndexScaleAndOpacities back{.index = index, .scaleAndOpacities = scaleAndOpacities};
    mIndexScaleAndOpacitiesList.append(std::move(back));
}

void TextAutoGenerateHistoryListViewDelegate::removeNeedUpdateWaitingAnswerAnimation(const QPersistentModelIndex &index)
{
    auto it = std::find_if(mIndexScaleAndOpacitiesList.cbegin(),
                           mIndexScaleAndOpacitiesList.cend(),
                           [index](const TextAutoGenerateDelegateUtils::IndexScaleAndOpacities &key) {
                               return key.index == index;
                           });
    if (it != mIndexScaleAndOpacitiesList.cend()) {
        mIndexScaleAndOpacitiesList.erase(it);
    }
}

#include "moc_textautogeneratehistorylistviewdelegate.cpp"
