//
//  SuperTuxKart - a fun racing game with go-kart
//  Copyright (C) 2009-2013 Joerg Henrichs
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

//#include "xml_node.h"
//#include "../utils/string_utils.h"
#include "map.h"
#include "../graphics/irr_driver.h"
#include <vector2d.h>
#include <vector3d.h>
#include "../utils/string_utils.h"
#include "../graphics/material_manager.h"
#include "../graphics/CBatchingMesh.h"
#include "../graphics/mesh_tools.h"

#include "../main.h"


Map::Map(const std::string &dirname)
{

    m_dirname              = dirname;
    m_root                  =
        StringUtils::getPath(StringUtils::removeExtension(m_dirname));
    m_ident                 = StringUtils::getBasename(m_root);
    m_root                 += "/";
    m_default_ambient_color = video::SColor(55, 120, 220, 120);

}

void Map::reset()
{
    Log::warn("[Map]", "reset does nothing yet!!");
/*
    m_ambient_color = m_default_ambient_color;
    CheckManager::get()->reset(*this);
    ItemManager::get()->reset();
    m_track_object_manager->reset();
    m_startup_run = false;
    */
}   // reset

void Map::update(float dt)
{
    Log::warn("[Map]", "update does nothing yet!!");

}

bool Map::checkNodeForTextures(irr::scene::IMesh * mesh)
{
    irr::video::IVideoDriver* driver = irr_driver->getDevice()->getVideoDriver();



    for (int i = 0; i < mesh->getMeshBufferCount(); i++)
        {
            irr::scene::IMeshBuffer * mb = mesh->getMeshBuffer(i);
            irr::video::SMaterial& mat = mb->getMaterial();

            //material_manager->setAllMaterialFlags(mat.getTexture(0), mb);
        }
    return true;
}

//--------------------------------------------------------------------------------------------

bool Map::loadMainMap(const XMLNode &root)
{

    Log::info("Map::loadMainMap", "loading map");
    const XMLNode *map_node = root.getNode("map");
    std::string model_name;
    map_node->get("model", &model_name);

    std::string full_path = m_root + model_name;
    scene::IMesh *mesh;

    mesh = irr_driver->getMesh(full_path.c_str());


if(!mesh)
    {
        Log::fatal("map",
                   "Main map model '%s' in '%s' not found, aborting.\n",
                   map_node->getName().c_str(),  model_name.c_str());

    }


    scene::CBatchingMesh *merged_mesh = new scene::CBatchingMesh();
    merged_mesh->addMesh(mesh);
    merged_mesh->finalize();

    scene::IMesh* tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap);


    scene::ISceneNode *scene_node = irr_driver->addMesh(tangent_mesh, "map_main");


    m_all_cached_meshes.push_back(tangent_mesh);
    irr_driver->grabAllTextures(tangent_mesh);

    // The reference count of the mesh is 1, since it is in irrlicht's
    // cache. So we only have to remove it from the cache.

    irr_driver->removeMeshFromCache(mesh);



    core::vector3df xyz(0,0,0);
    map_node->getXYZ(&xyz);
    core::vector3df hpr(0,0,0);
    map_node->getHPR(&hpr);
    scene_node->setPosition(xyz);
    scene_node->setRotation(hpr);
    //handleAnimatedTextures(scene_node, *map_node);
    m_all_nodes.push_back(scene_node);

    // Increase the maximum height of the track: since items that fly
    // too high explode, e.g. cakes can not be show when being at the
    // top of the track (since they will explode when leaving the AABB
    // of the track). While the test for this in Flyable::updateAndDelete
    // could be relaxed to fix this, it is not certain how the physics
    // will handle items that are out of the AABB



    /*
    for (unsigned int i=0; i<map_node->getNumNodes(); i++)
    {
        const XMLNode *n=map_node->getNode(i);
        // Animated textures have already been handled
        if(n->getName()=="animated-texture") continue;
        // Only "object" entries are allowed now inside of the model tag
        if(n->getName()!="static-object")
        {
            Log::error("track",
                "Incorrect tag '%s' inside <model> of scene file - ignored\n",
                    n->getName().c_str());
            continue;
        }


        core::vector3df xyz(0,0,0);
        n->get("xyz", &xyz);
        core::vector3df hpr(0,0,0);
        n->get("hpr", &hpr);
        core::vector3df scale(1.0f, 1.0f, 1.0f);
        n->get("scale", &scale);
    }
    */






    //scene_node->setMaterialFlag(video::EMF_LIGHTING, false); //set to true later !!!
    //scene_node->setMaterialFlag(video::EMF_GOURAUD_SHADING, true);

    return true;



}

void Map::loadMapModel()
{
    //irr_driver->setTextureErrorMessage("While loading map '%s'",
    //                                   m_filename                  );

    //const std::string& dirname = "maptest_map/";
    const XMLNode *map_node;

    file_manager->pushTextureSearchPath(m_root);

    //materials here
// TODO (sintel#1#): add TrackMode / MapMode here

    std::string path = "scene.xml";
    XMLNode *root    = file_manager->createXMLTree(path);

        if (!root || root->getName()!="scene")
    {
        std::ostringstream msg;
        msg<< "No map model defined in '"<<path
           <<"', aborting.";
        throw std::runtime_error(msg.str());
    }
    loadMainMap(*root);

    file_manager->popTextureSearchPath();
    //file_manager->popModelSearchPath  ();

    //map_node = file_manager->createXMLTree(dirname + "scene.xml");
    //loadMainMap(*map_node);


}   // loadTrackModel

//-----------------------------------------------------------------------------
/** Removes all cached data structures. This is called before the resolution
 *  is changed.
 */
void Map::removeCachedData()
{
    //error
    //m_materials_loaded = false;
}   // cleanCachedData
