// Contar las palabras de un texto. Viene hecho: el tema del paso 3 es elegir las k mayores.
#ifndef WORD_COUNT_H
#define WORD_COUNT_H

#include <cstddef>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>

#include "words.h"

struct WordCount {
    std::string word;
    long count = 0;
};

// El orden de la salida: más veces primero y, si empatan, el orden de bytes de la palabra.
struct MoreFrequent {
    bool operator()(const WordCount& a, const WordCount& b) const {
        if (a.count != b.count) {
            return a.count > b.count;
        }
        return a.word < b.word;
    }
};

inline std::string read_text(const std::string& path) {
    std::ifstream in(path, std::ios::binary);
    if (!in) {
        throw std::runtime_error("no se pudo abrir " + path);
    }
    return std::string(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>());
}

// Una entrada por cada palabra distinta del texto, en cualquier orden.
inline std::vector<WordCount> count_words(const std::string& text) {
    std::unordered_map<std::string, long> counts;
    for (const std::string& word : split_words(text)) {
        counts[word]++;
    }
    std::vector<WordCount> result;
    result.reserve(counts.size());
    for (const auto& [word, count] : counts) {
        result.push_back({word, count});
    }
    return result;
}

#endif
