#pragma once
#include "../../AutoLBA/auto_lba.hpp"
#include "../../Auxiliary/circular_buffer.hpp"
#include "../../Auxiliary/lz4_decompressor.hpp"
#include "../../System/IOPorts/cd_io.hpp"
#include "../cd_file_types.hpp"
#include "file_processor.hpp"

extern "C" uint32_t __heap_start;

namespace JabyEngine {
    class CDFileProcessor {
    public:
        struct BufferConfiguration {
            static constexpr size_t SmallSectorCount  = 5;
            static constexpr size_t MediumSectorCount = 16;

            uint32_t* adr          = nullptr;
            size_t    sector_count = 0;

            static constexpr BufferConfiguration new_default() {
                return {&__heap_start, BufferConfiguration::MediumSectorCount};
            }
        };

        struct JobArray {
            const CDFile* files = nullptr;
            size_t        size  = 0;

            bool next() {
                this->files += 1;
                this->size  -= 1;

                return this->size > 0;
            }
        };

    private:
        FileProcessor::State              file_state;
        CircularBuffer<CD_IO::DataSector> circular_buffer;
        LZ4Decompressor                   lz4_decomp;
        JobArray                          jobs;

        void start_cur_job(const AutoLBAEntry* lba, const BufferConfiguration& buf_cfg);
        bool process_data();

    public:
        CDFileProcessor() = default;

        void setup(const volatile AutoLBAEntry* lba, JobArray jobs, const BufferConfiguration& buf_cfg);
        void shutdown();

        template<size_t N>
        void setup(const volatile AutoLBAEntry* lba, const CDFile (&file_array)[N], const BufferConfiguration& buf_cfg) {
            CDFileProcessor::setup(lba, JobArray{file_array, N}, buf_cfg);
        }
        
        Progress process();
        
        bool next(const volatile AutoLBAEntry* lba, const BufferConfiguration& buf_cfg) {
            if(this->jobs.next()) {
                CDFileProcessor::start_cur_job(const_cast<const AutoLBAEntry*>(lba), buf_cfg);
                return true;
            }

            return false;
        }
    };
}