// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
// SPDX-License-Identifier: LGPL-2.0-or-later

#include "searchmodel.h"
#include "messageeventmodel.h"
#include "neochatroom.h"
#include "neochatuser.h"
#include <KLocalizedString>
#include <connection.h>

#ifdef QUOTIENT_07
#include <csapi/search.h>
#endif

using namespace Quotient;

// TODO search only in the current room

SearchModel::SearchModel(QObject *parent)
    : QAbstractListModel(parent)
{
}

QString SearchModel::searchText() const
{
    return m_searchText;
}

void SearchModel::setSearchText(const QString &searchText)
{
    m_searchText = searchText;
    Q_EMIT searchTextChanged();
}

void SearchModel::search()
{
#ifdef QUOTIENT_07
    Q_ASSERT(m_connection);
    setSearching(true);
    if (m_job) {
        m_job->abandon();
        m_job = nullptr;
    }

    SearchJob::RoomEventsCriteria criteria{
        m_searchText,
        {},
        RoomEventFilter{
            .rooms = {m_room->id()},
        },
        "recent",
        SearchJob::IncludeEventContext{3, 3, true},
        false,
        none,
    };

    auto job = m_connection->callApi<SearchJob>(SearchJob::Categories{criteria});
    m_job = job;
    connect(job, &BaseJob::finished, this, [=] {
        beginResetModel();
        m_result = job->searchCategories().roomEvents;
        endResetModel();
        setSearching(false);
        m_job = nullptr;
        // TODO error handling
    });
#endif
}

Connection *SearchModel::connection() const
{
    return m_connection;
}

void SearchModel::setConnection(Connection *connection)
{
    m_connection = connection;
    Q_EMIT connectionChanged();
}

QVariant SearchModel::data(const QModelIndex &index, int role) const
{
#ifdef QUOTIENT_07
    auto row = index.row();
    const auto &event = *m_result->results[row].result;
    switch (role) {
    case DisplayRole:
        return m_room->eventToString(*m_result->results[row].result);
    case ShowAuthorRole:
        return true;
    case AuthorRole:
        return QVariantMap{
            {"isLocalUser", event.senderId() == m_room->localUser()->id()},
            {"id", event.senderId()},
            {"avatarMediaId", m_connection->user(event.senderId())->avatarMediaId(m_room)},
            {"avatarUrl", m_connection->user(event.senderId())->avatarUrl(m_room)},
            {"displayName", m_connection->user(event.senderId())->displayname(m_room)},
            {"display", m_connection->user(event.senderId())->name()},
            {"color", dynamic_cast<NeoChatUser *>(m_connection->user(event.senderId()))->color()},
            {"object", QVariant::fromValue(m_connection->user(event.senderId()))},
        };
    case ShowSectionRole:
        if (row == 0) {
            return true;
        }
        return event.originTimestamp().date() != m_result->results[row - 1].result->originTimestamp().date();
    case SectionRole:
        return renderDate(event.originTimestamp());
    case TimeRole:
        return event.originTimestamp();
    }
    return MessageEventModel::DelegateType::Message;
#endif
    return {};
}

int SearchModel::rowCount(const QModelIndex &parent) const
{
#ifdef QUOTIENT_07
    if (m_result.has_value()) {
        return m_result->results.size();
    }
#endif
    return 0;
}

QHash<int, QByteArray> SearchModel::roleNames() const
{
    return {
        {EventTypeRole, "eventType"},
        {DisplayRole, "display"},
        {AuthorRole, "author"},
        {ShowSectionRole, "showSection"},
        {SectionRole, "section"},
        {TimeRole, "time"},
        {ShowAuthorRole, "showAuthor"},
    };
}

NeoChatRoom *SearchModel::room() const
{
    return m_room;
}

void SearchModel::setRoom(NeoChatRoom *room)
{
    m_room = room;
    Q_EMIT roomChanged();
}

// TODO deduplicate with messageeventmodel
QString renderDate(const QDateTime &timestamp)
{
    auto date = timestamp.toLocalTime().date();
    if (date == QDate::currentDate()) {
        return i18n("Today");
    }
    if (date == QDate::currentDate().addDays(-1)) {
        return i18n("Yesterday");
    }
    if (date == QDate::currentDate().addDays(-2)) {
        return i18n("The day before yesterday");
    }
    if (date > QDate::currentDate().addDays(-7)) {
        return date.toString("dddd");
    }

    return QLocale::system().toString(date, QLocale::ShortFormat);
}

bool SearchModel::searching() const
{
    return m_searching;
}

void SearchModel::setSearching(bool searching)
{
    m_searching = searching;
    Q_EMIT searchingChanged();
}
