//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007-2008)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: type.cpp
//      Краткое описание: type from file
//

#include <Darkstar/Resource System/Text/type.hpp>
#include <Darkstar/Kernel/parser.hpp>
#include <Darkstar/Kernel/FileSystem/dfile.hpp>
#include <Darkstar/Resource System/Textures/textureManager.hpp>
#include <Darkstar/Kernel/logh.hpp>

using ker::DFile;
using ker::Parser;
using ker::Section;
using rs::BaseTexture;
using rs::Type;
using rs::TypeChar;
using ker::PairInfo;
using rs::TypeTexture;
using rs::TextureChar;
using math::Vect2;
using rs::TextureManager;
using math::vect2_zero;
using ker::Log;

Type::Type()
{
	
};

Type::~Type()
{
	
};

bool Type::create(const std::string& filename)
{
	DFile file(filename);
	if(!file.getIsLoaded())
	{
		lwar << "Cannot open file with font description";
		return false;
	};

	Parser p(file);
	if(!p.getIsParsedSuccessfully())
	{
		lwar << "There was errors during parsing file with font description";
		return false;
	};
	shared_ptr<Section> root = p.getRootSection();
#ifdef _NOTFINAL
	if(root->values.size() != 1)
	{
		lwar << "File format error in line " << root->values.begin()->second.line_in_file;
		return false;
	};
#endif
	std::map<std::string, PairInfo>::iterator it;
	it = root->values.find("font_name");
	if(it == root->values.end())
	{
		lwar << "Cannot find font name";
		return false;
	};
	name = it->second.value;
	for(unsigned int i = 0; i < root->sections.size(); ++i)
	{
		shared_ptr<Section> next_section = root->sections[i];
		if(next_section->section_name == "texture")
		{
			std::string texture_name = next_section->section_value;
			unsigned int ref;
#ifdef _NOTFINAL
			if(next_section->values.size() > 1 || next_section->sections.size() > 0)
			{
				lwar << "File format error. In texture section can be only ref field. Section start at " << next_section->section_start_line;
				type_textures.clear();			
				return false;
			};
#endif
			it = next_section->values.find("ref");
			if(it == next_section->values.end())
			{
				lwar << "Cannot find ref field in texture description";
				type_textures.clear();
				return false;
			}
			else
			{
				ref = (unsigned int)atoi(it->second.value.c_str());
				shared_ptr<BaseTexture> new_type_tex = TextureManager::ptr()->load(texture_name);
				TypeTexture tt;
				tt.ref = ref;
				tt.texture = new_type_tex;
				type_textures.push_back(tt);
			};
			continue;
		};
		if(next_section->section_name == "char")
		{
#ifdef _NOTFINAL
			if(next_section->sections.size() > 0 || next_section->values.size() != 6 || next_section->section_value.size() == 0)
			{
				lwar << "File format error. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			};
#endif
			char ch;
			if(next_section->section_value.size() == 1)
				ch = next_section->section_value[0];
			else
				if(next_section->section_value == "eq")
					ch = '=';
				else
					if(next_section->section_value == "spc")
						ch = ' ';
					else
					{
						lwar << "File format error in section " << next_section->section_start_line;
						type_textures.clear();
						return false;
					};
			TypeChar chdesc;
			it = next_section->values.find("ref");
			if(it == next_section->values.end())
			{
				lwar << "Each char section must contains ref field. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			}
			else
				chdesc.ref = (unsigned int)atoi(it->second.value.c_str());
			
			it = next_section->values.find("sizex");
			if(it == next_section->values.end())
			{
				lwar << "Each char section must contains sizex field. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			}
			else
				chdesc.sizex = (unsigned int)atoi(it->second.value.c_str());

			it = next_section->values.find("sizey");
			if(it == next_section->values.end())
			{
				lwar << "Each char section must contains sizey field. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			}
			else
				chdesc.sizey = (unsigned int)atoi(it->second.value.c_str());

			it = next_section->values.find("tx");
			if(it == next_section->values.end())
			{
				lwar << "Each char section must contains tx field. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			}
			else
				chdesc.tx = (unsigned int)atoi(it->second.value.c_str());

			it = next_section->values.find("ty");
			if(it == next_section->values.end())
			{
				lwar << "Each char section must contains ty field. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			}
			else
				chdesc.ty = (unsigned int)atoi(it->second.value.c_str());

			it = next_section->values.find("aw");
			if(it == next_section->values.end())
			{
				lwar << "Each char section must contains aw field. Section start at line " << next_section->section_start_line;
				type_textures.clear();
				return false;
			}
			else
				chdesc.aw = (unsigned int)atoi(it->second.value.c_str());
			chars.insert(std::pair<char, TypeChar>(ch, chdesc));
			continue;
		};
		lwar << "File format error. Section has not correct name. Line: " << next_section->section_start_line;
		return false;
	};
	if(type_textures.size() == 0)
	{
		lwar << "Each type description file must contains at least one texture section";
		return false;
	};
	return true;
};

unsigned int Type::getTypeTexturesNumber() const
{
	return (unsigned int)type_textures.size();
};

const shared_ptr<BaseTexture>& Type::getTypeTextureByRef(const unsigned int ref) const
{
	return type_textures[ref].texture;
};

TextureChar Type::getChar(const char ch) const
{
	TextureChar tc;
	tc.tex_coord.ld_corner = vect2_zero;
	tc.tex_coord.rd_corner = vect2_zero;
	tc.tex_coord.lu_corner = vect2_zero;
	tc.tex_coord.ru_corner = vect2_zero;
	tc.texture_ref = 0;
	std::map<char, TypeChar>::const_iterator it = chars.find(ch);
	if(it == chars.end())
	{
		lwar << "This char " << ch << " don't contains in type " << name;
		return tc;
	};
	TypeChar type_char = it->second;
	tc.texture_ref = type_char.ref;
	unsigned int texture_width = type_textures[type_char.ref].texture->getWidth();
	unsigned int texture_height = type_textures[type_char.ref].texture->getHeight();
	float rs = (float)type_char.tx + (float)type_char.sizex;
	rs /= texture_width;
	float ds = (float)type_char.ty + (float)type_char.sizey;
	ds /= texture_height;
	float tx = (float)type_char.tx / texture_width;
	float ty = (float)type_char.ty / texture_height;
	tc.tex_coord.aw = type_char.aw;
	tc.tex_coord.height = type_char.sizey;
	tc.tex_coord.width = type_char.sizex;
	tc.tex_coord.lu_corner = Vect2(tx, ty);
	tc.tex_coord.ru_corner = Vect2(rs, ty);
	tc.tex_coord.ld_corner = Vect2(tx, ds);
	tc.tex_coord.rd_corner = Vect2(rs, ds);
	return tc;
};

const std::string& Type::getName() const
{
	return name;
};

