#pragma once

#include <filesystem>
#include <fstream>
#include <ranges>

#include "MaaUtils/Conf.h"

MAA_NS_BEGIN

template <typename ValueType>
concept ByteValueType = std::is_integral_v<ValueType> && sizeof(ValueType) == 1;

template <typename ContainerType>
concept AppendableBytesContainer = requires(ContainerType a) {
    requires std::ranges::contiguous_range<ContainerType>;
    requires ByteValueType<typename ContainerType::value_type>;
    requires std::is_constructible_v<ContainerType>;
    requires std::is_constructible_v<ContainerType, size_t,
                                     typename ContainerType::value_type>; // std::string(count, ch),
    // std::vector(count, value)
    a.insert(a.end(), a.begin(), a.begin() + 1);
    a.resize(a.size());
};

template <AppendableBytesContainer ContainerType>
ContainerType read_file(const std::filesystem::path& path)
{
    ContainerType result;
    std::ifstream file(path, std::ios::binary | std::ios::ate);
    if (!file.is_open()) {
        return result;
    }

    auto fileSize = file.tellg();
    if (fileSize != -1) {
        result.resize(fileSize);
        file.seekg(0, std::ios::beg);
        file.read(reinterpret_cast<char*>(result.data()), fileSize);
    }
    else {
        // no size available, read to EOF
        constexpr auto chunksize = 4096;
        ContainerType chunk(chunksize, 0);
        while (!file.fail()) {
            file.read(reinterpret_cast<char*>(chunk.data()), chunksize);
            result.insert(result.end(), chunk.data(), chunk.data() + file.gcount());
        }
    }
    return result;
}

MAA_NS_END
