#include "Engine.h"

cLevelManager::cLevelManager(std::string Name, int TileSize) : cRenderObject(Name)
{
    m_LevelTiles = SDL_LoadBMP("Tiles.bmp");
    m_TileSize = TileSize;

    createLevels();

    //Create player sprite
    m_Player = new cSprite("sprite", 2, 50);
    m_Player->loadSprite("player.bmp", true, SDL_MapRGB(screen->format, 255, 0, 0));

    m_CrateTile = g_TextureManager.loadSurface("Crate.bmp");

    m_PlayerPosX = m_PlayerPosY = 0;

    selectLevel(1);
}

bool cLevelManager::setPlayerPos(int x, int y)
{
    m_PlayerPosX = y;
    m_PlayerPosY = x;

    m_Player->m_XPos = y * m_TileSize;
    m_Player->m_YPos = x * m_TileSize;

    return true;
}

void cLevelManager::selectLevel(unsigned int Level)
{
    if(Level < m_Levels.size())
    {
        m_CurrentLevel = *m_Levels[Level];
        setPlayerPos(m_CurrentLevel.m_PlayerStartPosX, m_CurrentLevel.m_PlayerStartPosY);
    }
}

bool cLevelManager::doMove(SDLKey Key)
{
    unsigned int indexX = m_PlayerPosY;
    unsigned int indexY = m_PlayerPosX;
    unsigned int boxspaceX = indexX;
    unsigned int boxspaceY = indexY;

    switch(Key)
    {
        case SDLK_UP:
        {
            indexX--;
            boxspaceX = indexX - 1;
        }
        break;

        case SDLK_DOWN:
        {
            indexX++;
            boxspaceX = indexX + 1;
        }
        break;

        case SDLK_LEFT:
        {
            indexY--;
            boxspaceY = indexY - 1;
        }
        break;

        case SDLK_RIGHT:
        {
            indexY++;
            boxspaceY = indexY + 1;
        }
        break;

        default:
        break;
    }


    if((m_CurrentLevel.m_Level[indexX][indexY] == OBJECT_EMPTY) || (m_CurrentLevel.m_Level[indexX][indexY] == OBJECT_DEST))
    {
        //Check box array
        if(m_CurrentLevel.m_CrateArray[indexX][indexY] == OBJECT_BOX)
        {
            if(m_CurrentLevel.m_CrateArray[boxspaceX][boxspaceY] == OBJECT_BOX)
                return false;

            if(m_CurrentLevel.m_Level[boxspaceX][boxspaceY] == OBJECT_WALL)
                return false;

            m_CurrentLevel.m_CrateArray[indexX][indexY] = OBJECT_EMPTY;
            m_CurrentLevel.m_CrateArray[boxspaceX][boxspaceY] = OBJECT_BOX;
        }

        setPlayerPos(indexX, indexY);
    }

    return false;
}

void cLevelManager::createLevels()
{
    //Level 1

    cLevel* Level1 = new cLevel();

    Level1->m_LevelNumber = 0;

    Level1->m_Level[0][2] = OBJECT_WALL;
    Level1->m_Level[0][3] = OBJECT_WALL;
    Level1->m_Level[0][4] = OBJECT_WALL;
    Level1->m_Level[1][2] = OBJECT_WALL;
    Level1->m_Level[1][4] = OBJECT_WALL;
    Level1->m_Level[2][2] = OBJECT_WALL;
    Level1->m_Level[2][4] = OBJECT_WALL;
    Level1->m_Level[2][5] = OBJECT_WALL;
    Level1->m_Level[2][6] = OBJECT_WALL;
    Level1->m_Level[2][7] = OBJECT_WALL;
    Level1->m_Level[3][0] = OBJECT_WALL;
    Level1->m_Level[3][1] = OBJECT_WALL;
    Level1->m_Level[3][2] = OBJECT_WALL;
    Level1->m_Level[3][7] = OBJECT_WALL;
    Level1->m_Level[4][0] = OBJECT_WALL;
    Level1->m_Level[4][5] = OBJECT_WALL;
    Level1->m_Level[4][6] = OBJECT_WALL;
    Level1->m_Level[4][7] = OBJECT_WALL;
    Level1->m_Level[5][0] = OBJECT_WALL;
    Level1->m_Level[5][1] = OBJECT_WALL;
    Level1->m_Level[5][2] = OBJECT_WALL;
    Level1->m_Level[5][3] = OBJECT_WALL;
    Level1->m_Level[5][5] = OBJECT_WALL;
    Level1->m_Level[6][3] = OBJECT_WALL;
    Level1->m_Level[6][5] = OBJECT_WALL;
    Level1->m_Level[7][3] = OBJECT_WALL;
    Level1->m_Level[7][4] = OBJECT_WALL;
    Level1->m_Level[7][5] = OBJECT_WALL;

    //End marks
    Level1->m_Level[1][3] = OBJECT_DEST;
    Level1->m_Level[4][1] = OBJECT_DEST;
    Level1->m_Level[6][4] = OBJECT_DEST;
    Level1->m_Level[3][6] = OBJECT_DEST;

    Level1->m_PlayerStartPosX = 4;
    Level1->m_PlayerStartPosY = 4;

    //Place the boxes
    Level1->m_CrateArray[3][3] = OBJECT_BOX;
    Level1->m_CrateArray[3][4] = OBJECT_BOX;
    Level1->m_CrateArray[4][3] = OBJECT_BOX;
    Level1->m_CrateArray[5][4] = OBJECT_BOX;

    m_Levels.push_back(Level1);


    //Level 2

    cLevel* Level2 = new cLevel();

    Level2->m_LevelNumber = 1;

    Level2->m_Level[0][1] = OBJECT_WALL;
    Level2->m_Level[0][2] = OBJECT_WALL;
    Level2->m_Level[0][3] = OBJECT_WALL;
    Level2->m_Level[0][4] = OBJECT_WALL;
    Level2->m_Level[1][0] = OBJECT_WALL;
    Level2->m_Level[1][1] = OBJECT_WALL;
    Level2->m_Level[1][4] = OBJECT_WALL;
    Level2->m_Level[1][5] = OBJECT_WALL;
    Level2->m_Level[1][6] = OBJECT_WALL;
    Level2->m_Level[1][7] = OBJECT_WALL;
    Level2->m_Level[2][0] = OBJECT_WALL;
    Level2->m_Level[2][7] = OBJECT_WALL;
    Level2->m_Level[3][0] = OBJECT_WALL;
    Level2->m_Level[3][4] = OBJECT_WALL;
    Level2->m_Level[3][7] = OBJECT_WALL;
    Level2->m_Level[4][0] = OBJECT_WALL;
    Level2->m_Level[4][4] = OBJECT_WALL;
    Level2->m_Level[4][5] = OBJECT_WALL;
    Level2->m_Level[4][7] = OBJECT_WALL;
    Level2->m_Level[5][0] = OBJECT_WALL;
    Level2->m_Level[5][5] = OBJECT_WALL;
    Level2->m_Level[5][7] = OBJECT_WALL;
    Level2->m_Level[6][0] = OBJECT_WALL;
    Level2->m_Level[6][1] = OBJECT_WALL;
    Level2->m_Level[6][7] = OBJECT_WALL;
    Level2->m_Level[7][1] = OBJECT_WALL;
    Level2->m_Level[7][2] = OBJECT_WALL;
    Level2->m_Level[7][7] = OBJECT_WALL;
    Level2->m_Level[8][2] = OBJECT_WALL;
    Level2->m_Level[8][3] = OBJECT_WALL;
    Level2->m_Level[8][4] = OBJECT_WALL;
    Level2->m_Level[8][5] = OBJECT_WALL;
    Level2->m_Level[8][6] = OBJECT_WALL;
    Level2->m_Level[8][7] = OBJECT_WALL;

    Level2->m_PlayerStartPosX = 3;
    Level2->m_PlayerStartPosY = 5;

    Level2->m_Level[5][6] = OBJECT_DEST;
    Level2->m_Level[6][5] = OBJECT_DEST;
    Level2->m_Level[6][6] = OBJECT_DEST;
    Level2->m_Level[7][5] = OBJECT_DEST;
    Level2->m_Level[7][6] = OBJECT_DEST;

    Level2->m_CrateArray[2][4] = OBJECT_BOX;
    Level2->m_CrateArray[3][2] = OBJECT_BOX;
    Level2->m_CrateArray[3][3] = OBJECT_BOX;
    Level2->m_CrateArray[4][2] = OBJECT_BOX;
    Level2->m_CrateArray[6][3] = OBJECT_BOX;

    m_Levels.push_back(Level2);
}

void cLevelManager::update(SDL_Surface *Screen)
{
    if((Screen) && (m_LevelTiles))
    {
        for(int indx1 = 0; indx1 < 20; indx1++)
            for(int indx2 = 0; indx2 < 20; indx2++)
            {
                GAME_TYPE_OBJECT Index = m_CurrentLevel.m_Level[indx1][indx2];

                SDL_Rect SourceRct;
                SourceRct.x = Index * m_TileSize; SourceRct.w = m_TileSize;
                SourceRct.y= 0; SourceRct.h = m_TileSize;

                SDL_Rect DestRct;
                DestRct.x = indx2 * m_TileSize; DestRct.w = m_TileSize;
                DestRct.y = indx1 * m_TileSize; DestRct.h = m_TileSize;

                SDL_BlitSurface(m_LevelTiles, &SourceRct, Screen, &DestRct);

                //Draw boxes
                if(m_CurrentLevel.m_CrateArray[indx1][indx2] == OBJECT_BOX)
                {
                    DestRct.x = indx2 * m_TileSize; DestRct.w = m_TileSize;
                    DestRct.y = indx1 * m_TileSize; DestRct.h = m_TileSize;
                    SDL_BlitSurface(m_CrateTile, NULL, Screen, &DestRct);
                }

                  //Draw player object

                m_Player->update(Screen);
            }
    }
}

bool cLevelManager::checkForWin()
{
    for(int indx1 = 0; indx1 < 20; indx1++)
        for(int indx2 = 0; indx2 < 20; indx2++)
        {
            GAME_TYPE_OBJECT Index = m_CurrentLevel.m_Level[indx1][indx2];

            if(Index == OBJECT_DEST)
                if(m_CurrentLevel.m_CrateArray[indx1][indx2] != OBJECT_BOX)
                    return false;
        }

    return true;
}

bool cLevelManager::updateKey(SDLKey Key)
{
    switch(Key)
    {
        case SDLK_UP:
        case SDLK_LEFT:
        case SDLK_RIGHT:
        case SDLK_DOWN:
            doMove(Key);
            return true;
        break;

        case SDLK_r:
            selectLevel(m_CurrentLevel.m_LevelNumber);
            return true;
        break;

        default:
        break;
    }

    return true;
}
