#include <util/digest/fnv.h>
#include <util/string/builder.h>

#include <library/cpp/getopt/last_getopt.h>
#include <mapreduce/yt/interface/client.h>
#include <wmconsole/version3/wmcutil/yt/yt_utils.h>

#include "partition.h"
#include "run_config.h"
#include "task_digest_messages.h"
#include "util.h"

namespace NWebmaster {

namespace {
//const char *FIELD_HOST                  = "Host";
const char *FIELD_REPORT                = "Report";
const char *FIELD_USER_SETTINGS         = "UserSettings";

const char *SUBFIELD_EMAIL              = "email";
const char *SUBFIELD_USER_ID            = "user_id";
//const char *SUBFIELD_LOGIN              = "login";
//const char *SUBFIELD_FIO                = "fio";
const char *SUBFIELD_HOST_ID            = "host_id";
const char *SUBFIELD_LANG               = "language";
const char *SUBFIELD_NOTIFICATION_TYPE  = "notification_type";
}

void PackDigestMessages(const NYT::TNode &row, TStringBuilder &data) {
    const TRunConfig &config = TRunConfig::CInstance();
    const auto &settings = row[FIELD_USER_SETTINGS];
    if (NYTUtils::IsNodeNull(settings[SUBFIELD_EMAIL])) {
        return;
    }
    data << config.DateFieldValue << "\t"
         << PrintNumOrDefault(settings, SUBFIELD_USER_ID, 0) << "\t"
         << settings[SUBFIELD_HOST_ID].AsString() << "\t"
         << encode(settings[SUBFIELD_EMAIL].AsString()) << "\t"
         << settings[SUBFIELD_LANG].AsString() << "\t"
         << settings[SUBFIELD_NOTIFICATION_TYPE].AsString() << "\t"
         << encode(row[FIELD_REPORT].AsString()) << "\n";
}

void TMapDigestMessages::Do(TReader *reader, TWriter *writer) {
    const TRunConfig &config = TRunConfig::CInstance();
    TStringBuilder data;
    for (; reader->IsValid(); reader->Next()) {
        ui64 userId = reader->GetRow()[FIELD_USER_SETTINGS][SUBFIELD_USER_ID].AsUint64();
        ui64 hash = FnvHash<size_t>(ToString(userId));
        size_t partId = hash % config.TablesCount;
        hash /= config.TablesCount;
        size_t lineId = hash % config.LinesCount;
        PackDigestMessages(reader->GetRow(), data);
        if (data.Size() > 0) {
            writer->AddRow(NYT::TNode()
                               (TReduceCompressPartition::F_PARTITION_ID, partId)
                               (TReduceCompressPartition::F_LINE_ID, lineId)
                               (TReduceCompressPartition::F_ROW_ID, reader->GetRowIndex())
                               (TReduceCompressPartition::F_DATA, data)
            );
        }
        data.clear();
    }
}

} //namespace NWebmaster
