#ifndef _ISong_H
#define _ISong_H

#include "TimTypes.h"
#include "Song.h"
#include "Channel.h"
#include "Controller.h"
#include "Instrument.h"
#include "NoteHandler.h"
#include "TimLib:Seq.h"

#define swrk_status_playing         0x00000001
#define swrk_status_paused          0x00000002
#define swrk_status_linked          0x00000004
#define swrk_status_alwayslink      0x00000008
#define swrk_status_pauseatend      0x00000010
#define swrk_status_pauseatpattern  0x00000020
#define swrk_status_pauseatrow      0x00000040
#define swrk_status_pauseatframe    0x00000080
#define swrk_status_tempoisbpm      0x20000000
#define swrk_status_processrow      0x40000000
#define swrk_status_noramp          0x80000000
#define swrk_status_altermask       0x000000F8
#define swrk_status_readmask        0x000000FF


#define swrk_change_row             0x00000001
#define swrk_change_pattern         0x00000002

#define swrk_max_loops 256

typedef struct ILoop
{
	uint32_t    count;
	uint16_t    row;
	int16_t     last;
} ILoop;

typedef struct ISection
{
	const SubSong*  pSubSong; // Sub-song the section is part of
	uint32_t        StartPos; // Starting pos in sub-song order sequence
} ISection;

struct ISong
{
	SongHdr         Hdr; // header for loaders
	void*           pFReadNote;
	SeqHandler      Seq;
	uint32_t*       pMergedSeqs;
	uint32_t        Status;
	uint32_t        Config;
	uint32_t        ConfigAmp;
	uint32_t        PreAmp;
	struct
	{
	  int32_t       Start;       // >= 0 seqeunce range start else normal play
	  int32_t       Last;        // sequence range end
	  int32_t       Pattern;     // >= 0 to play a given pattern
	} PlayRange;
	uint32_t        CurrentTempo;
	uint32_t        CurrentSpeed;
	Controller      Volume;
	Controller      Tempo;
	Controller      Speed;
	uint32_t        TicksPerBeat; // if <> 0 Tempo is Beats per minutes
	uint32_t        TempoTime;   // duration of one frame in 1/256 us (256000000/tempo)
	uint32_t        FrameTime;   // time spend in current frame
	uint32_t        Frames;      // nr of frames per row = speed * (1 + row delay)
	uint32_t        FrameCount;  // nr of frames spend in current row
	uint32_t        FrameExtCount; // nr of frames spend in current row + repeats
	uint32_t        Repeats;     // nr of row repeats
	uint32_t        RepeatCount; // nr of row repeats spend in current row
	uint32_t        TimeIndex;   // in 1/250 ms
	uint32_t        RampCount;
	uint32_t        RowPos;
	const uint8_t*  RowPtr;
	const uint8_t*  EffectsPtr;
	struct
	{
		uint32_t       Rows;
		const uint8_t* Ptr;
	} Pattern;
	uint32_t        SongTime; // in 1/250 ms
	uint32_t        SeqsChange;
	const SubSong*  SubSongPtr;
	uint32_t        SeqPos;
	Channel*        ChannelsPtr;
	ILoop*          LoopsInfoPtr;
	ISection*       SectionsPtr;
	uint32_t        LoopsCount;
	uint32_t        LoopsActiveNr;
	NoteHandler     Notes;
	Pattern         patterns[song_max_patterns];
	Instrument      instruments[song_max_instruments];
	Sample          samples[song_max_samples + 2];
	uint32_t        Tag;
	Channel         channels[song_max_channels];
	ILoop           loops[swrk_max_loops];
	uint8_t         MarkRow[song_max_rows];
};

#endif
