#pragma once
#include <luna/Result.h>
#include <luna/String.h>
#include <luna/Types.h>
#include <sys/types.h>

class TarStream
{
  public:
    enum class EntryType
    {
        RegularFile,
        Directory,
        Unimplemented,
    };

    struct Entry
    {
        String name;
        usize size;
        mode_t mode;
        uid_t uid;
        gid_t gid;
        EntryType type;

        const u8* data() const
        {
            return m_data;
        }

      private:
        u8* m_data;

        friend class TarStream;
    };

    TarStream() = default;
    TarStream(void* base, usize size);

    void initialize(void* base, usize size);

    Result<bool> read_next_entry(Entry& out);

    void rewind();

  private:
    struct [[gnu::packed]] TarHeader
    {
        char name[100];
        char mode[8];
        char uid[8];
        char gid[8];
        char size[12];
        char mtime[12];
        char chksum[8];
        char typeflag;
        char linkname[100];
        char magic[6];
        char version[2];
        char uname[32];
        char gname[32];
        char devmajor[8];
        char devminor[8];
        char prefix[155];
    };

    void find_valid_header(TarHeader* out, bool& success);

    void read_header(TarHeader* out, bool& success);
    Result<Entry> parse_header(const TarHeader* hdr);

    void* m_base;
    void* m_pos;
    usize m_size;
    usize m_offset = 0;
};