#ifndef DSHASH_HPP
#define DSHASH_HPP

#include <array>
#include <string>
#include <vector>
#include <cstdint>
#include <filesystem>

typedef std::array<uint8_t, 32> tHash;

class DSHash {
public:    
    explicit DSHash(const std::filesystem::path& path);
    explicit DSHash(const std::string& str);
    
    std::string toString();
    tHash get();
    
private:
    std::string hashString(const std::string& str);
    std::string hashFile(const std::filesystem::path& filepath);
    std::string hashDirectory(const std::filesystem::path& dirpath);

    void update(const uint8_t* data, size_t length);
    void update(const std::string& str);
    tHash finalize();

private:
    void processBlock(const uint8_t* block);
    void padMessage();
    
    static constexpr size_t BLOCK_SIZE = 64;
    
    std::vector<uint8_t> buffer;
    uint64_t total_length = 0;
    uint32_t h[8];
    bool finalized = false;
    
    static const uint32_t K[64];
};

#endif