#pragma once
#include <PSX/jabyengine_config.hpp>
#include "../Overlay/overlay.hpp"
#include "file_types.hpp"

namespace JabyEngine {
    using CDFileType_t = uint8_t;
    using RawPayload_t = uint32_t;

    enum struct CDFileType : CDFileType_t {
        CopyTo = 0,
        SimpleTIM,
        SonyTIM,
        SonyVAG,
        Custom,
    };

    #pragma pack(push, 1)
    struct CDFile {
        union Payload {
            RawPayload_t raw;
            CopyTo       copy_to;
            SimpleTIM    simple_tim;
            TIM          tim;
            VAG          vag;
            Overlay      overlay;
        };

        uint8_t    rel_lba_idx;
        CDFileType type;
        Payload    payload;

        template<typename S>
        static constexpr CDFile custom(uint8_t lba_idx, S cd_file_type, RawPayload_t raw) {
            return CDFile{
                .rel_lba_idx = lba_idx, 
                .type        = static_cast<CDFileType>(static_cast<CDFileType_t>(CDFileType::Custom) + static_cast<CDFileType_t>(cd_file_type)),
                .payload     = {.raw = raw}
            };
        }
        static_assert(sizeof(Payload) == sizeof(uint32_t));
    };
    #pragma pack(pop)

    struct CDFileBuilder {
        static constexpr CDFile copy_to(uint8_t rel_lba_idx, uint32_t* dst) {
            return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.copy_to = CopyTo{dst}}};
        }

        static constexpr CDFile simple_tim(uint8_t rel_lba_idx, SimpleTIM simple_tim) {
            return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::SimpleTIM, .payload = {.simple_tim = simple_tim}};
        }

        static constexpr CDFile sony_tim(uint8_t rel_lba_idx, TIM tim) {
            return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::SonyTIM, .payload = {.tim = tim}};
        }

        static constexpr CDFile sony_vag(uint8_t lba_idx, VAG vag) {
            return CDFile{.rel_lba_idx = lba_idx, .type = CDFileType::SonyVAG, .payload = {.vag = vag}};
        }

        static constexpr CDFile overlay(uint8_t rel_lba_idx, uint32_t* overlay_dst) {
            return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.overlay = Overlay{overlay_dst}}};
        }
    };
}