#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include <string>
#include <vector>
#include <math.h>
#include <fstream>

using namespace std;

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include "PersoPrincipal.h"
#include "Map.h"
#include "Moteur.h"
#include "Define.h"


int Split(vector<string>* vecteur, string chaine, char separateur)
{

    vecteur->resize(1);
    vecteur[0].empty();

    int longeur = chaine.length();

    for(int i = 0; i < longeur; ++i)
    {

        if(chaine.at(i) == separateur)
        {
            vecteur->resize(vecteur->size() + 1);
        }
        else
        {
            vecteur->at(vecteur->size() - 1).resize(vecteur->at(vecteur->size() - 1).size() + 1);
            vecteur->at(vecteur->size() - 1).at(vecteur->at(vecteur->size() - 1).size() - 1) = chaine.at(i);
            vecteur->at(vecteur->size() - 1).at(vecteur->at(vecteur->size() - 1).size() - 1) = chaine.at(i);
        }

    }

    return vecteur->size();

}

CMap::CMap()
{
	//Constructeur publique!!!
}

CMap::~CMap()
{
	//Destructeur Publique ...
}

void CMap::RenderMap(int PersoX, int PersoY)
{
	int index = 0, x, y, w, h;

	w = LARGEUR_ECRAN/2 - PersoX;
	if(w > 0) w = 0;
	if(w < -Largeur*64 + LARGEUR_ECRAN) w = -Largeur*64 + LARGEUR_ECRAN;

	h = HAUTEUR_ECRAN/2 - PersoY;
	if(h > 0) h = 0;
	if(h < -Hauteur*64 + HAUTEUR_ECRAN) h = -Hauteur*64 + HAUTEUR_ECRAN;
	
	glMatrixMode(GL_MODELVIEW); 

	glTranslated(w, h, 0);

	for(x = 0; x < Largeur; x++)
	{
		for(y = 0; y < Hauteur; y++)
		{
			index = TablMap[x][y];

			if(index > 1)
			{
				Moteur.AfficheTexture(TexturesMap[index], x * 64, y * 64, 64, 64);
			}
		}
	}

	int nbanim = int((SDL_GetTicks() % 1000) / 100);
	for(int i = 0; i < Bonus.size(); i++)
		Moteur.AfficheTexture(TexturesBonus[(Bonus[i].TypeBonus - 1) * 10 + nbanim], Bonus[i].CarreauX * 64, Bonus[i].CarreauY * 64, 64, 64);

}

CMainPerso* CMap::LoadMap(const char *filename)
{

	char temp[1000], ch;
	string strTemp;

	sprintf(temp, "./Data/Maps/%s", filename);

	ifstream fichier(temp);

    string Fichier;
    vector<string> Parties;
    
    Personnages.clear();

    while(fichier.get(ch))
        Fichier += ch;

    int nbParties = Split(&Parties, Fichier, '[');

    for(int sousPartie = 1; sousPartie < nbParties; ++sousPartie)
    {
        vector<string> SousParties;

        Split(&SousParties, Parties[sousPartie], ']');

        string Nom = SousParties[0];
        string Valeur = SousParties[1];

        if(Nom == "Infos")
        {

			vector<string> Infos;

            int nbInfos = Split(&Infos, Valeur, '\n');

            for(int i = 0; i < nbInfos; ++i)
            {
					if(Infos[i] != "")
					{
						vector<string> VecStrInfo;

						Split(&VecStrInfo, Infos[i], '=');

						if(VecStrInfo[0] == "Hauteur")
							Hauteur = atoi(VecStrInfo[1].c_str());

						if(VecStrInfo[0] == "Largeur")
							Largeur = atoi(VecStrInfo[1].c_str());

						if(VecStrInfo[0] == "PosDebutX")
							PosDebutX = atoi(VecStrInfo[1].c_str());

					if(VecStrInfo[0] == "PosDebutY")
						PosDebutY = atoi(VecStrInfo[1].c_str());
                }
            }
        }
			else if(Nom == "Perso")
			{
				vector<string> lignes, partieslignes;
				
				
				Split(&lignes, Valeur, '\n');
				
				for(int i = 0; i < lignes.size(); ++i)
				{
					partieslignes.clear();
					Split(&partieslignes, lignes[i], '/');
					
					if(partieslignes.size() == 4)
					{
						CPerso* newperso = new CPerso();
						newperso->ModifPos(atoi(partieslignes[0].c_str()), atoi(partieslignes[1].c_str()));
						newperso->TexPerso(partieslignes[2].c_str());
						newperso->SetIA(partieslignes[3]);
						Personnages.push_back(newperso);
					}
				}
			}
        else if(Nom == "Map")
        {
            TablMap.resize(Largeur);

            for(int i = 0; i < Largeur; ++i)
                TablMap[i].resize(Hauteur, 0);

            vector<string> ligneMap;

            int nbLignes = Split(&ligneMap, Valeur, '\n');

            char ch;
            int y = 0;

            for(int ligne = 0; ligne < nbLignes; ++ligne)
            {
                if(ligneMap[ligne] != "")
                {
                    for(int x = 0; x < Largeur; ++x)
                    {
                        ch = ligneMap[ligne][x];

						if(ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8') TablMap[x][y] = VIDE;

						if(ch == ' ') TablMap[x][y] = VIDE;
						else if(ch == 'B') TablMap[x][y] = HERBE;
						else if(ch == 'b') TablMap[x][y] = TERRE;
						else if(ch == 'C') TablMap[x][y] = EAU;
						else if(ch == 'M') TablMap[x][y] = MUR_DROITE;
						else if(ch == 'm') TablMap[x][y] = MUR_GAUCHE;
						else if(ch == 'D') TablMap[x][y] = DEBUT_PENTE_DROITE;
						else if(ch == 'd') TablMap[x][y] = DEBUT_PENTE_GAUCHE;
						else if(ch == 'P') TablMap[x][y] = PENTE_DROITE;
						else if(ch == 'p') TablMap[x][y] = PENTE_GAUCHE;
						else if(ch == 'T') TablMap[x][y] = TRANSITION_DROITE;
						else if(ch == 't') TablMap[x][y] = TRANSITION_GAUCHE;
						else if(ch == 'S') TablMap[x][y] = SOMMET_COTE_DROITE;
						else if(ch == 's') TablMap[x][y] = SOMMET_COTE_GAUCHE;
						else if(ch == 'V') TablMap[x][y] = HERBE_VIDE_DROITE;
						else if(ch == 'v') TablMap[x][y] = HERBE_VIDE_GAUCHE;
						else if(ch == 'X') TablMap[x][y] = TRANSITION_MUR_TERRE_HAUT_DROITE;
						else if(ch == 'x') TablMap[x][y] = TRANSITION_MUR_TERRE_HAUT_GAUCHE;
						else if(ch == 'H') TablMap[x][y] = TRANSITION_MUR_TERRE_DROITE;
						else if(ch == 'h') TablMap[x][y] = TRANSITION_MUR_TERRE_GAUCHE;
						else if(ch == 'R') TablMap[x][y] = TRANSITION_MUR_TERRE_BAS_DROITE;
						else if(ch == 'r') TablMap[x][y] = TRANSITION_MUR_TERRE_BAS_GAUCHE;
						else if(ch == 'O') TablMap[x][y] = TRANSITION_MUR_HERBE_DROITE;
						else if(ch == 'o') TablMap[x][y] = TRANSITION_MUR_HERBE_GAUCHE;
						else if(ch == 'W') TablMap[x][y] = TRANSITION_MUR_EAU_DROITE;
						else if(ch == 'w') TablMap[x][y] = TRANSITION_MUR_EAU_GAUCHE;
						else if(ch == 'A') TablMap[x][y] = SABLE;
						else if(ch == 'a') TablMap[x][y] = SABLE_SOL;
						else if(ch == 'E') TablMap[x][y] = SABLE_VIDE_DROITE;
						else if(ch == 'e') TablMap[x][y] = SABLE_VIDE_GAUCHE;
						else if(ch == 'I') TablMap[x][y] = SABLE_MUR_DROITE;
						else if(ch == 'i') TablMap[x][y] = SABLE_MUR_GAUCHE;
						else if(ch == '1') AddBonus(x, y, BONUS_VIE_25P);
						else if(ch == '2') AddBonus(x, y, BONUS_VIE_50P);
						else if(ch == '3') AddBonus(x, y, BONUS_VIE_75P);
						else if(ch == '4') AddBonus(x, y, BONUS_VIE_100P);
						else if(ch == '5') AddBonus(x, y, BONUS_MANA_25P);
						else if(ch == '6') AddBonus(x, y, BONUS_MANA_50P);
						else if(ch == '7') AddBonus(x, y, BONUS_MANA_75P);
						else if(ch == '8') AddBonus(x, y, BONUS_MANA_100P);

                    }
                    ++y;
                }
            }
        }
    }

	CMainPerso* tempperso = new CMainPerso();
	
	tempperso->TexPerso("Principal");
	tempperso->ModifPos((PosDebutX - 1) * 64, (PosDebutY - 1) * 64);
	tempperso->SetIA(IA_AUCUNE);
	
	return tempperso;
}

void CMap::LoadTextures()
{
	TexturesMap[HERBE] = Moteur.NouvelleTexture("Images/Maps/Herbe.png");
	TexturesMap[EAU] = Moteur.NouvelleTexture("Images/Maps/Eau.png");
	TexturesMap[MUR] = Moteur.NouvelleTexture("Images/Maps/Mur.png");
	TexturesMap[DEBUT_PENTE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Debut de pente droite.png");	      
	TexturesMap[SABLE_VIDE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Sable - Vers vide a gauche.png");
	TexturesMap[DEBUT_PENTE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Debut de pente gauche.png");	      
	TexturesMap[SOMMET_COTE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Sommet de cote droite.png");			      
	TexturesMap[SOMMET_COTE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Sommet de cote gauche.png");		      
	TexturesMap[TERRE] = Moteur.NouvelleTexture("Images/Maps/Terre.png");
	TexturesMap[HERBE_VIDE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Herbe vers le vide a droite.png");  
	TexturesMap[TRANSITION_DROITE] = Moteur.NouvelleTexture("Images/Maps/Transition cote droite.png");
	TexturesMap[HERBE_VIDE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Herbe vers le vide a gauche.png");  
	TexturesMap[TRANSITION_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Transition cote gauche.png");		      
	TexturesMap[TRANSITION_MUR_EAU_DROITE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-eau droite.png");
	TexturesMap[MUR_DROITE] = Moteur.NouvelleTexture("Images/Maps/Mur droite.png");			      
	TexturesMap[TRANSITION_MUR_EAU_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-eau gauche.png");
	TexturesMap[MUR_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Mur gauche.png");			      
	TexturesMap[TRANSITION_MUR_HERBE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-herbe droite.png");		      
	TexturesMap[TRANSITION_MUR_HERBE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-herbe gauche.png");
	TexturesMap[PENTE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Pente droite.png");		      
	TexturesMap[TRANSITION_MUR_TERRE_BAS_DROITE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-terre bas droite.png");
	TexturesMap[PENTE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Pente gauche.png");		      
	TexturesMap[TRANSITION_MUR_TERRE_BAS_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-terre  bas gauche.png");
	TexturesMap[SABLE] = Moteur.NouvelleTexture("Images/Maps/Sable - Interieur.png");	      
	TexturesMap[TRANSITION_MUR_TERRE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-terre droite.png");
	TexturesMap[SABLE_MUR_DROITE] = Moteur.NouvelleTexture("Images/Maps/Sable - Mur droite.png");	      
	TexturesMap[TRANSITION_MUR_TERRE_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-terre gauche.png");
	TexturesMap[SABLE_MUR_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Sable - Mur gauche.png");	      
	TexturesMap[TRANSITION_MUR_TERRE_HAUT_DROITE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-terre haut droite.png");
	TexturesMap[SABLE_SOL] = Moteur.NouvelleTexture("Images/Maps/Sable - Sol.png");		      
	TexturesMap[TRANSITION_MUR_TERRE_HAUT_GAUCHE] = Moteur.NouvelleTexture("Images/Maps/Transition mur-terre haut gauche.png");
	TexturesMap[SABLE_VIDE_DROITE] = Moteur.NouvelleTexture("Images/Maps/Sable - Vers vide a droite.png");

	int i;
	char nom[100];

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/vie25p%d.png", i);
		TexturesBonus[i - 1] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/vie50p%d.png", i);
		TexturesBonus[i + 9] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/vie75p%d.png", i);
		TexturesBonus[i + 19] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/vie100p%d.png", i);
		TexturesBonus[i + 29] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/mana25p%d.png", i);
		TexturesBonus[i + 39] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/mana50p%d.png", i);
		TexturesBonus[i + 49] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/mana75p%d.png", i);
		TexturesBonus[i + 59] = Moteur.NouvelleTexture(nom);
	}

	for(i = 1; i <= 10; i++)
	{
		sprintf(nom, "Images/Bonus/mana100p%d.png", i);
		TexturesBonus[i + 69] = Moteur.NouvelleTexture(nom);
	}
}

bool CMap::AutAcces(int X, int Y)
{

	div_t ty = div(Y, 64);
	int caseY = ty.quot;
	int posY = ty.rem;

	div_t tx = div(X, 64);
	int caseX = tx.quot;
	int posX = tx.rem;
	
	switch(TablMap[caseX][caseY])
	{
		case VIDE:
		case EAU:
			return true;
			break;
			
		case HERBE:
		case MUR:
		case SABLE_VIDE_DROITE:
		case DEBUT_PENTE_DROITE:
		case DEBUT_PENTE_GAUCHE:
		case TERRE:
		case HERBE_VIDE_DROITE:
		case TRANSITION_DROITE:
		case HERBE_VIDE_GAUCHE:
		case TRANSITION_GAUCHE:
		case TRANSITION_MUR_EAU_DROITE:
		case MUR_DROITE:
		case TRANSITION_MUR_EAU_GAUCHE:
		case MUR_GAUCHE:
		case TRANSITION_MUR_HERBE_DROITE:
		case TRANSITION_MUR_HERBE_GAUCHE:
		case TRANSITION_MUR_TERRE_BAS_DROITE:
		case TRANSITION_MUR_TERRE_BAS_GAUCHE:
		case SABLE:
		case TRANSITION_MUR_TERRE_DROITE:
		case SABLE_MUR_DROITE:
		case TRANSITION_MUR_TERRE_GAUCHE:
		case SABLE_MUR_GAUCHE:
		case TRANSITION_MUR_TERRE_HAUT_DROITE:
		case SABLE_SOL:
		case TRANSITION_MUR_TERRE_HAUT_GAUCHE:
		case SABLE_VIDE_GAUCHE:
			return false;
			break;

		case SOMMET_COTE_GAUCHE:
		case PENTE_GAUCHE:
			posX = 64 - posX;
		case PENTE_DROITE:
		case SOMMET_COTE_DROITE:
			return (posY < posX);
			break;
	}

}

bool CMap::DiedAcces(int X, int Y)
{

	div_t ty = div(Y, 64);
	int caseY = ty.quot;

	div_t tx = div(X, 64);
	int caseX = tx.quot;

	return (TablMap[caseX][caseY] == EAU);
}

int CMap::ReturnPosDebutX()
{
	return (PosDebutX - 1) * 64;
}

int CMap::ReturnPosDebutY()
{
	return (PosDebutY - 1) * 64;
}

CMap::CBonus::CBonus()
{

}


CMap::CBonus::~CBonus()
{

}


void CMap::AddBonus(int CX, int CY, int Type)
{
	CBonus NewBonus;
	NewBonus.CarreauX = CX;
	NewBonus.CarreauY = CY;
	NewBonus.TypeBonus = Type;

	Bonus.push_back(NewBonus);
}

int CMap::ReturnBonus(int X, int Y)
{
	int CX = (X+32)/64;
	int CY = (Y+32)/64;
	int type;

	for(int i = 0; i < Bonus.size(); i++)
	{
		if(Bonus[i].CarreauX == CX && Bonus[i].CarreauY == CY)
		{
			type = Bonus[i].TypeBonus;
			Bonus.erase(Bonus.begin() + i);
			return type;
		}
	}
	return BONUS_ERREUR;
}


char CMap::ReturnTypeCarreau(int X, int Y)
{
	return TablMap[X][Y];
}

