#include "DevLib.h"
/******************************************************************************
 * Level.cpp                                                                  *
 ******************************************************************************
 * Project      : Futura (DevLib Demo)                                        *
 * License      : LGPL (full notice can be found at root directory)           *
 * Created by   : Arnaud Storq (norecess@devlib-central.org)                  *
 ******************************************************************************/
#include "Level.h"
#include "Application.h"

// ---------------------------------------------------------------------------- DEFINE
#define TRACK_WIDTH         9   

#define TILES_COUNT         6

// ---------------------------------------------------------------------------- TILE XML TRANSLATION
static struct TileXMLTranslation
{
    TileType tileType;
    char nodeName[ 32 ];
} s_tileXMLTranslation[ TILES_COUNT ] =
{
    TILE_EMPTY,         "",
    TILE_SLOW,          "tileSlow",
    TILE_NORMAL,        "tileNormal",
    TILE_FAST,          "tileFast",
    TILE_VERYFAST,      "tileVeryFast",
    TILE_CUBE,          "cube"
};

// ---------------------------------------------------------------------------- CONSTRUCTOR
Level::Level( int index )
{
    XMLNode *levelsNode = Application::getInstance( )->getXML( )->getRoot( )->getChildElement( "levels" );
    int levelCount = levelsNode->getChildCount( );
    assert( index < levelCount );

    XMLNode *levelNode = levelsNode->getChildElement( index );

    // load track
    string trackFilename = levelNode->getChildElement( "track" )->getChildElement( )->getString( );
    
    Resource *resource = Resource::createResource( trackFilename );
    assert( resource );

    unsigned char *buffer = (unsigned char *) resource->getBuffer( );
    for ( int i = 0; i < resource->getSize( ); ++i )
    {
        switch( buffer[ i ] )
        {
        case 'S':       m_track.push_back( TILE_SLOW );         break;
        case 'F':       m_track.push_back( TILE_FAST );         break;
        case 'f':       m_track.push_back( TILE_VERYFAST );     break;
        case 'X':       m_track.push_back( TILE_NORMAL );       break;
        case 'C':       m_track.push_back( TILE_CUBE );         break;
        case '0':
        case 's':
                        m_track.push_back( TILE_EMPTY );        break;
        }
    }

    delete resource;

    // background
    string backgroundFilename = levelNode->getChildElement( "background" )->getChildElement( )->getString( );
    string cloudsFilename = levelNode->getChildElement( "clouds" )->getChildElement( )->getString( );

    Application::getInstance( )->getBackground( )->setTextures( backgroundFilename, cloudsFilename );

    // ship envmap
    string envmapFilename = levelNode->getChildElement( "shipEnvmap" )->getChildElement( )->getString( );
    m_shipEnvmap = Texture::createTexture( false, envmapFilename );
    
    // tiles
    for ( int tile = 0; tile < TILES_COUNT; ++tile )
    {
        string filename;
        string nodeName( s_tileXMLTranslation[ tile ].nodeName );
        if ( nodeName != "" )
        {
            filename = levelNode->getChildElement( nodeName )->getChildElement( )->getString( );
        }
        m_tiles.push_back( Tile::createTile( s_tileXMLTranslation[ tile ].tileType, filename ) );
    }

    // track speed
    m_trackSpeed = levelNode->getChildElement( "speed" )->getChildElement( )->getFloat( );

    // default jump count applied to players
    m_startJumpCount = levelNode->getChildElement( "jumpCount" )->getChildElement( )->getInt( );

    // music
    string soundFilename = levelNode->getChildElement( "music" )->getChildElement( )->getString( );
    m_music = Sound::createSound( soundFilename );
}

// ---------------------------------------------------------------------------- DESTRUCTOR
Level::~Level( )
{
    delete m_shipEnvmap;
    
    m_music->stop( );
    delete m_music;

    for ( int tile = 0; tile < (int) m_tiles.size( ); ++tile )
    {
        delete m_tiles[ tile ];
    }
}

// ---------------------------------------------------------------------------- CREATE LEVEL
Level *Level::createLevel( int index )
{
    return new Level( index );
}

// ---------------------------------------------------------------------------- GET TRACK WIDTH
int Level::getTrackWidth( )
{
    return TRACK_WIDTH;
}

// ---------------------------------------------------------------------------- GET TRACK HEIGHT
int Level::getTrackHeight( )
{
    return m_track.size( ) / TRACK_WIDTH;
}

// ---------------------------------------------------------------------------- GET TRACK TILE
TileType Level::getTrackTile( int x, int y )
{
    if ( ( x < 0 ) || ( x >= TRACK_WIDTH ) || ( y < 0 ) || ( y >= getTrackHeight( ) ) )
    {
        return TILE_EMPTY;
    }

    assert( ( x >= 0 ) && ( x < TRACK_WIDTH ) );
    assert( ( y >= 0 ) && ( y < getTrackHeight( ) ) );

    return m_track[ ( y * TRACK_WIDTH ) + x ];
}

// ---------------------------------------------------------------------------- GET TILE
Tile *Level::getTile( TileType tileType )
{
    for ( int tile = 0; tile < (int) m_tiles.size( ); ++tile )
    {
        if ( m_tiles[ tile ]->getType( ) == tileType )
            return m_tiles[ tile ];
    }

    assert( false );
    return 0;
}
