#pragma once
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<stdint.h>
#include<SDL/SDL.h>
#undef main




struct decoder{
    struct info{
        enum INTYPE{
            TYPE_FILE = 0,
            TYPE_MEM
        };
        int(*output_callback)(void*,const void*,int);
        void* output_userdata;
        INTYPE input_type;
        void* input_data;
        int input_length;
        const char* input_filename;
        void* codecspecific;
        int desired_samplerate;
        int desired_bps;
        int desired_channels;
        int desired_sblen;
    };
    struct samples{
        private:
            void* data;
            int len;
            int readpos;
            int writepos;
            int resetprotected;
            bool doreset;
            SDL_mutex* writing;
            void PRIVATERESET();
        public:
            void lock();
            void unlock();
            void preventreset();
            void permitreset();
            samples();
            ~samples();
            void reserve(int amnt);
            void push( const void* buff, int length );
            int pull( void* buff, int length );
            int pullfrom(void* buff, int length, int posit);
            int pullreadonly( void** buff, int length );
            void rewind();
            bool eof();
            void reset();
            int totallength();
            int pos();
    };
    struct indata{
        void* data;
        int len;
        int pos;
        indata( void* d = 0, int l = 0 );
        indata( const char* fname );
        ~indata();
        void seek( int whence, int offset );
        void seek( void* position );
        void* get(int length, int* lremaining);
        void* get(void* buff, int length, int* lremaining);
        bool eof();
    } *data;
    struct outcb{
        int (*cb)(void* udata, const void* samples, int len);
        void* udat;
        outcb( void* u=0, int(*i)(void*,const void*,int)=0 );
        int operator()( const void* s, int l );
    } *output;
    int getfactor( int orate );
    int64_t mixsamples( int64_t a, int64_t b, uint8_t factor);
    int samplerate;
    int bps;
    int chan;
    int sblen;

    SDL_AudioSpec wavewave;
    uint8_t *wavedata;
    uint32_t wavedlen;
    SDL_AudioCVT wavecvt;

    samples samps;

    void __init__(info);
    void __destroy__();
    virtual void decode() = 0;

    decoder();
    decoder( decoder::info a );
    ~decoder();
};

