#include "CMountain.h"

CMountain::CMountain(core::stringc mapname)
{
    //printf("Mountain constructor mapname=%s \n",mapname.c_str());
    mountainMap=mapname;
}



void CMountain::LoadMountain()
{
	//Lecture du fichier map
	//printf("mountainMap=%s \n",mountainMap.c_str());
	const char* pathmap="maps/";
	const char* pathmedia="media/";
	core::stringc tmp=pathmap;
	tmp+=mountainMap;

	configFileName=tmp;

	arrStations.clear();

    //printf("mountainMap tmp=%s \n",tmp.c_str());
	//tmp.append("./maps/");
	//tmp.append(mountainMap);
    std::ifstream infile(configFileName.c_str(),std::ifstream::in);
    std::string line;
    //printf("Load file %s \n" , tmp.c_str());
    while (std::getline(infile, line))
    {
        printf("Line=%s \n" , line.c_str());
        const char hf[]="heightfield=";
        if(strstr(line.c_str(),hf))
        {
          heightfieldFilename=line.substr(12).c_str();
          //printf("heightfield file=%s \n" , heightfieldFilename.c_str());
        }

        const char textures[]="texture=";
        if(strstr(line.c_str(),textures))
        {
          terrainTextureFilename=line.substr(8).c_str();
          //printf("texture terrain file=%s \n", terrainTextureFilename.c_str());
        }

		const char station[]="station#";
		if(strstr(line.c_str(),station))
        {
          CStation *st=new CStation(smgr,driver);

		  core::array<std::string> v=explode(line.c_str(), '#');
		  //printf("explose %s v.size=%i \n" ,line.c_str(), v.size());
		  if(v.size()==3) {
			  core::stringc stationname=core::stringc(v[1].c_str());
			  st->SetName(stationname);
			  core::stringc strposition=core::stringc(v[2].c_str());
			  core::array<std::string> coords=explode(v[2], '-');

			  if(coords.size()==3) {
				  //printf("1 -> Place station au point %f  ; %f  \n" ,strtof(coords[0].c_str(),0),strtof(coords[2].c_str(),0));
				  core::vector3df vecPos=core::vector3df(strtof(coords[0].c_str(),0),strtof(coords[1].c_str(),0),strtof(coords[2].c_str(),0));
				  st->SetPosition(vecPos);
				  arrStations.push_back(st);
			  } else {
				  printf("ERREUR DANS LES COORDONNEES DE STATION %s DANS FICHIER MAP\n",stationname.c_str());
			  }
		  } else {
			  printf("ERREUR LORS DE CHARGEMENT D'UN OBJET TYPE STATION DANS FICHIER MAP\n");
		  }

        }

        //std::istringstream iss(line);
    }
    infile.close();

	// add terrain scene node
   core::stringc hfname=pathmap;
   hfname+=heightfieldFilename;
   terrain = smgr->addTerrainSceneNode(
        hfname,
        0,                  // parent node
        TERRAIN_NODE_ID,                 // node id
        core::vector3df(0.f, 0.f, 0.f),     // position
        core::vector3df(0.f, 0.f, 0.f),     // rotation
        core::vector3df(40.f, 20.f, 40.f),  // scale
        video::SColor ( 255, 255, 255, 255 ),   // vertexColor
        5,                  // maxLOD
        scene::ETPS_17,             // patchSize
        4                   // smoothFactor
        );

    terrain->setMaterialFlag(video::EMF_LIGHTING, false);

    core::stringc texturename=pathmap;
    texturename+=terrainTextureFilename;
    terrain->setMaterialTexture(0,driver->getTexture(texturename));
    /*terrain->setMaterialTexture(1,
            driver->getTexture("media/detailmap3.jpg"));*/

    terrain->setMaterialType(video::EMT_DETAIL_MAP);

    terrain->scaleTexture(1.0f, 20.0f);

	// create triangle selector for the terrain
    selector= smgr->createTerrainTriangleSelector(terrain, 0);
    terrain->setTriangleSelector(selector);

    //affiche la(es) stations
    for(unsigned i=0;i<arrStations.size();i++) {
        core::vector3df vecPos=arrStations[i]->GetPosition();
        //printf("Corrige Place station %i au point %f  ; %f ; %f \n" ,i,vecPos.X,GetHeight(vecPos,5000),vecPos.Z);
        arrStations[i]->DrawStation();
    }

	// create skybox
    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

    skybox=smgr->addSkyBoxSceneNode(
        driver->getTexture("media/snow_positive_y.jpg"),
        driver->getTexture("media/snow_negative_y.jpg"),
        driver->getTexture("media/snow_positive_z.jpg"),
        driver->getTexture("media/snow_negative_z.jpg"),
        driver->getTexture("media/snow_positive_x.jpg"),
        driver->getTexture("media/snow_negative_x.jpg"));

    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

}

core::vector3df CMountain::clickTerrainCoordinates() {
    gui::ICursorControl *cursor = device->getCursorControl();
    core::position2d<s32> mousePos = cursor->getPosition();

    printf("clickTerrainCoordinates mousepos : %i %i \n",mousePos.X,mousePos.Y);
    core::vector3df intersection;
    core::triangle3df hit_triangle;

    scene::ISceneCollisionManager* colMan = device->getSceneManager()->getSceneCollisionManager();
    scene::ISceneNode *node = 0;
    core::line3d<f32> ray = colMan->getRayFromScreenCoordinates(mousePos);

    /*scene::ISceneNode *selected_scene_node =
        colMan->getSceneNodeAndCollisionPointFromRay (
        ray,
        intersection, // On récupère ici les coordonnées 3D de l’intersection
        hit_triangle, // et le triangle intersecté
        CMountain::TERRAIN_NODE_ID); // On ne veut que des nœuds avec cet identifiant*/
    if(colMan->getCollisionPoint(ray, selector, intersection, hit_triangle, node)){
       if(node) {
        if(node->getID()==CMountain::TERRAIN_NODE_ID) {
                //printf("clickTerrainCoordinates : %f %f %f \n",intersection.X,intersection.Y,intersection.Z);
                return intersection;
            }
        } else {
             return core::vector3df (0,0,0);
        }
    }

    return core::vector3df (0,0,0);;
}

/*f32 CMountain::getTerrainHeight(f32 x,f32 z) {
    printf("getTerrainHeight %f,%f",x,z);
    return terrain->getHeight(x,z);
}*/

f32 CMountain::GetHeight(const core::vector3df& pos, f32 maxHeight)
{
   scene::ISceneCollisionManager* colMan = device->getSceneManager()->getSceneCollisionManager();

    //printf("P1 pos : %f %f %f \n",pos.X,pos.Y,pos.Z);
    core::vector3df yAxis(0,maxHeight,0);
    core::line3d<f32> ray(pos+yAxis, pos-yAxis);
    //printf("P2 pos : %f %f %f \n",pos-yAxis).X,pos.Y,pos.Z);
    //RenderLine(ray.start, ray.end);(


    core::vector3df intersection;
    core::triangle3df hitTriangle;
    scene::ISceneNode *outScenceNode;

    /*scene::ISceneNode *outScenceNode=colMan->getSceneNodeAndCollisionPointFromRay(
                    ray,
                    intersection, // This will be the position of the collision
                    hitTriangle, // This will be the triangle hit in the collision
                    TERRAIN_NODE_ID, // This ensures that only nodes that we have
                            // set up to be pickable are considered
                    0); // Che
    if(outScenceNode) {
        printf("outScenceNode not null");
        return intersection.Y;
    } else {
        printf("outScenceNode null");
        return -100.0f;
    }*/


    if(colMan->getCollisionPoint(ray, selector, intersection, hitTriangle,outScenceNode)) {
        if(outScenceNode!=0) {
             printf("GetHeight collisioninfo=%f\n",intersection.Y);
            return intersection.Y;
        } else {
            printf("GetHeight intersection est null\n");
            return -100.0f;
        }

    }
    else
    {
        return -100.0f;
    }
}

scene::ISceneNode* CMountain::getNodeByClick() {
    gui::ICursorControl *cursor = device->getCursorControl();
    core::position2d<s32> mousePos = cursor->getPosition();

    printf("getNodeByClick mousepos : %i %i \n",mousePos.X,mousePos.Y);
    core::vector3df intersection;
    core::triangle3df hit_triangle;

    scene::ISceneCollisionManager* colMan = device->getSceneManager()->getSceneCollisionManager();

    scene::ISceneNode *node = 0;
    core::line3d<f32> ray = colMan->getRayFromScreenCoordinates(mousePos);

    node=colMan->getSceneNodeAndCollisionPointFromRay(ray, intersection, hit_triangle, ARBRE_NODE_ID|TKF_NODE_ID|TSF2_NODE_ID, node);
    if(node) {
         printf("getNodeByClick arbre mousepos : %i %i %i\n",mousePos.X,mousePos.Y,node->getID());
         return node;
    }

    /*node=colMan->getSceneNodeAndCollisionPointFromRay(ray, intersection, hit_triangle, TKF_NODE_ID, node);
    if(node) {
         printf("getNodeByClick TK mousepos : %i %i %i\n",mousePos.X,mousePos.Y,node->getID());
         return node;
    }

    node=colMan->getSceneNodeAndCollisionPointFromRay(ray, intersection, hit_triangle,TSF2_NODE_ID, node);
    if(node) {
         printf("getNodeByClick TS mousepos : %i %i %i\n",mousePos.X,mousePos.Y,node->getID());
         return node;
    }*/


}

CArbre* CMountain::getArbreByID(core::stringc nom) {
     for(unsigned int i=0;i<arrArbres.size();i++) {
        if(arrArbres[i]->GetID()==nom) {
            return arrArbres[i];
        }
     }
}

CRemontee* CMountain::getRemonteeByID(core::stringc id) {
    for(unsigned int i=0;i<arrRemontees.size();i++) {
        if(arrRemontees[i]->GetID()==id) {
            return arrRemontees[i];
        }
     }
}

const core::array<std::string> CMountain::explode(const std::string& s, const char& c)
{
	std::string buff="";
	core::array<std::string> v;

	//for(auto n:s)
    for(unsigned int i=0;i<s.size();i++)
	{
		if(s[i] != c) {
           buff+=s[i];
		}  else {
		    if(s[i] == c && buff != "") {
                v.push_back(buff);
                buff = "";
		    }
		}
	}

	if(buff != "") {
        v.push_back(buff);
    }

	return v;
}

CMountain::~CMountain()
{
    if(terrain!=0) {
        delete terrain;
        terrain=0;
    }

    if(selector!=0) {
        delete selector;
        selector=0;
    }

    if(skybox!=0) {
        delete skybox;
        skybox=0;
    }

    if(driver!=0) {
        delete driver;
        driver=0;
    }

    if(smgr!=0) {
        delete smgr;
        smgr=0;
    }
}
