/*
 * Copyright (c) 2009 by Oleg Trifonov <otrifonow@gmail.com>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 */

#ifndef _MELODYFILE_H_
#define _MELODYFILE_H_

#include <string>
#include <map>
#include <vector>

#include "trStream.h"
#include "trStrUtils.h"

#include "wav.h"

// класс фрагмента мелодии (wav-файла или mel-файла)
class MelodyFile {
public:
	enum FragmentType {
		Wav,
		Mel
	};

	~MelodyFile();

	// компилирует фрагмент
	// выводит ошибки и предупреждения
	bool Compile();

	// сохраняет скомпилированный фрагмент в поток
	bool Write(TrStream &out);

	// возвращает смещение фрагмента относительно начала блока фрагментов
	UInt32 GetOffset();

	// возвращает размер бинарности для этой мелодии
	UInt32 GetSize();

	// выводит информацию о мелодии на экран
	void PrintInfo();

	// возвращает фрагмент мелодии по имени файла. если фрагмент получается впервые, то
	// загружает файл, иначе - возвращает уже загруженный
	static MelodyFile* Get(const char *filename);

	// компилирует все мелодии
	static bool CompileAll();

	// выводит все фрагменты в поток
	static bool WriteAll(TrStream &out);

	// выводит информацию всех мелодииях на экран
	static void PrintAll();

	// возвращает суммарный размер всех фрагментов
	static UInt32 GetTotalSize() { return currentOffset; };

private:
	std::string fileName;			// имя файла
	FragmentType type;				// тип фрагмента мелодии
	WavFile *wav;						// данные о wav-файле
	UInt32 offset;						// смещение в файле прошивки относительно начала относительно начала блока фрагментов
	TrMemStream *mel;					// скомпилированный код нотной мелодии
	std::string melody;				// строка мелодии для mel-файлов

	static UInt32 currentOffset;	// смещение, по которому будет загружена следующий фрагмент
	static std::map<std::string, MelodyFile*> fragments;


	MelodyFile();


	// загружает мелодию из файла	
	bool Open(const char *filename);

};


// мелодия звонка. может состоять из произвольного количества фрагментов
class CompositeMelody {
public:
	CompositeMelody();
	~CompositeMelody();

	// загружает из строки, содержащей список файов-фрагментов
	bool Load(std::string &s);

	// сохраняет мелодию в поток
	bool Write(TrStream &out, UInt32 fragmentsOffset);

	// возвращает смещение мелодии начала блока мелодий
	UInt32 GetOffset() { return offset; };

	// возвращает размер бинарности для этой мелодии
	UInt32 GetSize() { return (GetCount()+1)*4; };

	// возвращает количество фрагментов
	UInt32 GetCount() { return fileNames.size(); };

	// возвращает фрагмент
	MelodyFile* Get(UInt32 i) { return MelodyFile::Get(fileNames[i].c_str()); };

	// возвращает полный размер всех мелодий
	static UInt32 GetFullSize() { return currentOffset; };

private:
	std::vector<std::string> fileNames;
	UInt32 offset;
	static UInt32 currentOffset;
};


#endif // _MELODYFILE_H_