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

#include <library/cpp/getopt/last_getopt.h>
#include <mapreduce/yt/interface/client.h>

#include "partition.h"
#include "run_config.h"
#include "task_indexed.h"
#include "tasks.h"
#include "util.h"

namespace NWebmaster {

namespace {
const char *FIELD_HOST = "Host";
const char *FIELD_TIMESTAMP = "Timestamp";

const char *FIELD_HTTP_CODE = "HttpCode";
const char *FIELD_COUNT_CRAWLED = "CountCrawled";
}

void PackIndexedCount(const NYT::TNode &row, TStringBuilder &data) {
    const TRunConfig &config = TRunConfig::CInstance();
    data << config.DateFieldValue << "\t"
         << GetHostId(row[FIELD_HOST].AsString()) << "\t"
         << GetNodeId(row) << "\t"
         << GetJavaTimestamp(row, FIELD_TIMESTAMP) << "\t"
         << PrintNumOrDefault(row, FIELD_HTTP_CODE, 0) << "\t"
         << PrintNumOrDefault(row, FIELD_COUNT_CRAWLED, 0) << "\n";
}

size_t HashIndexedCount(const NYT::TNode &row) {
    const TString &host = row[FIELD_HOST].AsString();
    const time_t timestamp = row[FIELD_TIMESTAMP].AsInt64();
    return ComputeHash(host) + ComputeHash(LocalDateFromTime(timestamp));
}

void TMapIndexedCount::Do(TReader *reader, TWriter *writer) {
    const TRunConfig &config = TRunConfig::CInstance();
    TStringBuilder data;
    for (; reader->IsValid(); reader->Next()) {
        const NYT::TNode &row = reader->GetRow();
        const TString &hostId = GetHostId(row[FIELD_HOST].AsString());
        size_t partId = FnvHash<size_t>(hostId) % config.TablesCount;
        size_t hashSource = HashIndexedCount(row);
        size_t lineId = hashSource % config.LinesCount;
        PackIndexedCount(row, 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
