#pragma once

#include <yandex/maps/wiki/diffalert/message.h>

#include <cstdint>
#include <map>
#include <string>
#include <vector>

namespace maps {
namespace wiki {
namespace diffalert {

class StoredMessage;
typedef std::vector<StoredMessage> StoredMessages;

enum class RegionPriority
{
    High = 0,
    Medium = 1,
    Low = 2,
    Unimportant = 3
};

inline bool operator<(RegionPriority lhs, RegionPriority rhs)
{
    return static_cast<uint32_t>(lhs) < static_cast<uint32_t>(rhs);
}

enum class PostponeAction
{
    Postpone,
    Return
};

enum class HasOwnName
{
    Yes,
    No
};

class StoredMessage
{
public:
    StoredMessage(
            const Message& message,
            std::string categoryId,
            std::string objectLabel,
            HasOwnName hasOwnName,
            const Envelope& envelope);

    explicit StoredMessage(const pqxx::row& row);

    StoredMessageId id() const { return id_; };

    TId objectId() const { return objectId_; };
    Priority priority() const { return priority_; };
    const std::string& description() const { return description_; };

    const std::string& categoryId() const { return categoryId_; };
    const std::string& objectLabel() const { return objectLabel_; };
    HasOwnName hasOwnName() const { return hasOwnName_; }

    const Envelope& envelope() const { return envelope_; };

    TUId inspectedBy() const { return inspectedBy_; };
    const std::string& inspectedAt() const { return inspectedAt_; };

    bool postponed() const { return postponed_; };

    static StoredMessages markAsInspected(
            pqxx::transaction_base& txn,
            const std::vector<StoredMessageId>& messageIds,
            TUId uid);

    static StoredMessage postpone(
            pqxx::transaction_base& txn,
            StoredMessageId messageId,
            PostponeAction action);

private:
    StoredMessageId id_;

    TId objectId_;
    Priority priority_;
    std::string description_;

    std::string categoryId_;
    std::string objectLabel_;
    HasOwnName hasOwnName_;

    Envelope envelope_;

    TUId inspectedBy_;
    std::string inspectedAt_;

    bool postponed_;
};

struct MessageStatisticsItem
{
    uint32_t regionPriority;
    uint32_t majorPriority;
    std::string categoryId;
    std::string description;

    size_t totalCount;
    size_t inspectedCount;
};

using MessageStatistics = std::vector<MessageStatisticsItem>;

} // namespace diffalert
} // namespace wiki
} // namespace maps
