#ifndef _RIVE_RUNTIME_HEADER_HPP_
#define _RIVE_RUNTIME_HEADER_HPP_

#include "rive/core/binary_reader.hpp"
#include <unordered_map>

namespace rive
{

/// Rive file runtime header. The header is fonud at the beginning of every
/// Rive runtime file, and begins with a specific 4-byte format: "RIVE".
/// This is followed by the major and minor version of Rive used to create
/// the file. Finally the owner and file ids are at the end of header; these
/// unsigned integers may be zero.
static constexpr char kRuntimeHeaderFingerprint[] = "RIVE";
class RuntimeHeader
{
private:
    int m_MajorVersion;
    int m_MinorVersion;
    uint64_t m_FileId;
    std::unordered_map<int, int> m_PropertyToFieldIndex;

public:
    /// @returns the file's major version
    int majorVersion() const { return m_MajorVersion; }
    /// @returns the file's minor version
    int minorVersion() const { return m_MinorVersion; }
    /// @returns the file's id; may be zero
    uint64_t fileId() const { return m_FileId; }

    int propertyFieldId(int propertyKey) const
    {
        auto itr = m_PropertyToFieldIndex.find(propertyKey);
        if (itr == m_PropertyToFieldIndex.end())
        {
            return -1;
        }

        return itr->second;
    }

    /// Reads the header from a binary buffer/
    /// @param reader the binary reader attached to the buffer
    /// @param header a pointer to the header where the data will be stored.
    /// @returns true if the header is successfully read
    static bool read(BinaryReader& reader, RuntimeHeader& header)
    {
        for (int i = 0; i < 4; i++)
        {
            auto b = reader.readByte();
            if (kRuntimeHeaderFingerprint[i] != b)
            {
                return false;
            }
        }

        header.m_MajorVersion = reader.readVarUintAs<int>();
        if (reader.didOverflow())
        {
            return false;
        }
        header.m_MinorVersion = reader.readVarUintAs<int>();
        if (reader.didOverflow())
        {
            return false;
        }

        header.m_FileId = reader.readVarUint64();

        if (reader.didOverflow())
        {
            return false;
        }

        std::vector<int> propertyKeys;
        for (int propertyKey = reader.readVarUintAs<int>(); propertyKey != 0;
             propertyKey = reader.readVarUintAs<int>())
        {
            propertyKeys.push_back(propertyKey);
            if (reader.didOverflow())
            {
                return false;
            }
        }

        int currentInt = 0;
        int currentBit = 8;
        for (auto propertyKey : propertyKeys)
        {
            if (currentBit == 8)
            {
                currentInt = reader.readUint32();
                currentBit = 0;
            }
            int fieldIndex = (currentInt >> currentBit) & 3;
            header.m_PropertyToFieldIndex[propertyKey] = fieldIndex;
            currentBit += 2;
            if (reader.didOverflow())
            {
                return false;
            }
        }

        return true;
    }
};
} // namespace rive
#endif
