#pragma once

#include <vector>
#include <cstring>

namespace Vib {

class FamiText
{
public:
	static const int MAX_CHANNELS = 32;

	enum
	{
		NOTE_NONE = 0,
		NOTE_CUT,
		NOTE_OFF,
		NOTE_C0
	};

	struct Cell
	{
		unsigned char note, inst, vol;
		unsigned char etype[4];
		unsigned char eparam[4];
		Cell() { ::memset(this, 0, sizeof(*this)); }
	};

	FamiText();
	~FamiText();

	// resets and empties the FamiText
	void clear();

	// reads a Famitracker text file
	const char* read(const char* filename);

	// static info
	int get_channels() const;
	int get_frames() const;

	// playback
	void play(); // begin from start
	void tick(int ticks);
	Cell read_tick(int channel) const; // notes read in last tick
	int read_frame() const; // frame read in last tick

protected:
	void set_cell(int pattern, int row, int channel, Cell c);
	Cell get_cell(int pattern, int row, int channel) const;

	void set_order(int frame, int channel, unsigned char o);
	unsigned char get_order(int frame, int channel) const;

	int song_channels;
	int song_speed;
	int song_pattern_len;
	int song_frames;
	int song_columns[MAX_CHANNELS];
	int song_tempo;

	std::vector<unsigned char> order;
	std::vector<Cell> patterns;

	int play_frame;
	int play_row;
	int play_speed;
	int play_tempo;
	int play_tempo_accum;
	int play_gxx[MAX_CHANNELS];
	Cell play_gxx_hold[MAX_CHANNELS];

	Cell play_read[MAX_CHANNELS];
	int play_read_frame;
};

} // namespace Vib

// end of file
