#include "task_messages.h"
#include "common/magic_strings.h"

#include <mutex>

namespace maps::wiki::validator {

void TaskMessages::addMessage(
    Message message,
    TCheckId checkId,
    MessageKeyGenerator keyGenerator,
    MessageComparator messageComparator)
{
    auto key = keyGenerator(message);

    std::unique_lock<std::mutex> lock(mutex_);

    auto& checkMessages = messagesByCheck_[checkId];
    if (key == NO_DEDUPLICATION) {
        checkMessages.messages.push_back(std::move(message));
    } else {
        auto iter = checkMessages.messageKeyToPtr.find(key);
        if (iter == checkMessages.messageKeyToPtr.end()) {
            checkMessages.messages.push_back(std::move(message));
            checkMessages.messageKeyToPtr[key] = &checkMessages.messages.back();
        } else if (!messageComparator(*iter->second, message)) {
            *(iter->second) = std::move(message);
        }
    }
}

void TaskMessages::addBaseCheckMessages(MessageBuffer buffer)
{
    std::unique_lock<std::mutex> lock(mutex_);
    auto& baseCheckMessages = messagesByCheck_[BASE_CHECK_ID];
    baseCheckMessages.messages.splice(
        std::end(baseCheckMessages.messages), buffer);
}

MessageBuffer TaskMessages::popMessages()
{
    MessageBuffer result;
    std::unique_lock<std::mutex> lock(mutex_);
    for (auto& [_, checkMessages] : messagesByCheck_) {
        result.splice(std::end(result), checkMessages.messages);

        MessageKeyToPtr emptyMessageKeyToPtr;
        checkMessages.messageKeyToPtr.swap(emptyMessageKeyToPtr);
    }
    return result;
}

} // namespace maps::wiki::validator
