#pragma once
#include "ioport.hpp"

namespace JabyEngine {
    namespace CD_IO_Values {
        __declare_io_struct(AudioVolumeApply, uint8_t) {
            static constexpr auto Mute         = Bit(0);
            static constexpr auto ApplyChanges = Bit(5);
        };

        struct CDDAVolume {
            using Type = uint8_t;

            static constexpr uint8_t Off     = 0x0;
            static constexpr uint8_t Default = 0x80;
            static constexpr uint8_t Max     = 0xFF;
        };

        __declare_io_struct(CommandFifo, uint8_t) {
        };

        __declare_io_struct(DataFifo, uint8_t) {
        };

        __declare_io_struct(DataFifo16, uint16_t) {
        };

        __declare_io_struct(InterruptEnable, uint8_t) {
            static constexpr auto InterruptTypValue = BitRange::from_to(0, 2);
            static constexpr auto InterruptExtended = BitRange::from_to(0, 4);
            static constexpr auto UnknownIRQ        = Bit(3);
            static constexpr auto CommandStartIRQ   = Bit(4);
        };
        using InterruptFlag = InterruptEnable;

        __declare_io_struct(IndexStatus, uint8_t) {
            static constexpr auto PortIndex             = BitRange::from_to(0, 1);
            static constexpr auto HasXAFifoData         = Bit(2);
            static constexpr auto IsParameterFifoEmpty  = Bit(3);
            static constexpr auto HasParameterFifoSpace = Bit(4);
            static constexpr auto HasResponseFifoData   = Bit(5);
            static constexpr auto HasDataFifoData       = Bit(6);
            static constexpr auto IsTransmissionBusy    = Bit(7);
        };

        __declare_io_struct(LeftCD2LeftSPU, CDDAVolume::Type) {
        };

        __declare_io_struct(LeftCD2RightSPU, CDDAVolume::Type) {
        };

        __declare_io_struct(Mode, uint8_t) { 
            static constexpr auto DoubleSpeed    = Bit(7);
            static constexpr auto SingleSpeed    = !DoubleSpeed;
            static constexpr auto XADPCM         = Bit(6);
            static constexpr auto WholeSector    = Bit(5);
            static constexpr auto DataSector     = !WholeSector;
            static constexpr auto UseXAFilter    = Bit(3);
            static constexpr auto AudioPlayIRQ   = Bit(2);
            static constexpr auto AutoPauseTrack = Bit(1);
            static constexpr auto CDDA           = Bit(0);

            operator uint8_t() const {
                return this->raw;
            }
        };

        __declare_io_struct(ParameterFifo, uint8_t) {
        };

        __declare_io_struct(Request, uint8_t) {
            static constexpr auto WantCommandStartIRQ = Bit(5);
            static constexpr auto WantData            = Bit(7);

            static Request want_data() {
                return Request{static_cast<uint8_t>(Request::WantData)};
            }

            static Request reset() {
                return Request{0};
            }
        };

        __declare_io_struct(ResponseFifo, uint8_t) {
        };

        __declare_io_struct(RightCD2LeftSPU, CDDAVolume::Type) {
        };

        __declare_io_struct(RightCD2RightSPU, CDDAVolume::Type) {
        };

        __declare_io_struct(SoundMapCoding, uint8_t) {
            static constexpr auto Stereo             = Bit(0);
            static constexpr auto Mono               = !Stereo;
            static constexpr auto SampleRate_18900hz = Bit(2);
            static constexpr auto SampleRate_37800hz = !SampleRate_18900hz;
            static constexpr auto BitsPerSample8     = Bit(4);
            static constexpr auto BitsPerSample4     = !BitsPerSample8;
            static constexpr auto Emphasis           = Bit(6);
        };

        __declare_io_struct(SoundMapDataOut, uint8_t) {
        };
    }
}