/******************************************************************************
*	File		-	tile_map.h
*	Author		-	Joey Pollack
*	Date		-	2022/02/15 (y/m/d)
*	Mod Date	-	2022/02/15 (y/m/d)
*	Description	-	Contains a single tile map
******************************************************************************/

#include "tile_map.h"
#include "tile_set.h"
#include <core/core.h>
#include <graphics/graphics.h>

namespace lunarium { namespace editor
{
    
    TileMap::TileMap(std::map<int, TileSet*>* tilesets)
        : mpTileSets(tilesets), mpMap(nullptr)
    {

    }

    void TileMap::ClearMap()
    {
        for(int i = 0; i < mSizeInTiles.Width; i++)
        {
            for (int j = 0; j < mSizeInTiles.Height; j++)
            {
                mpMap[i][j] = { -1, {-1, -1} };
            }
        }
    }

    
    Sizei TileMap::GetSizeInTiles()
    {
        return mSizeInTiles;
    }

    Sizei TileMap::GetSizeInPixels()
    {
        if (!mpMap)
            return { 0, 0 };

        Sizei tile_size = (*mpTileSets)[mpMap[0][0].TileSetID]->GetTileSize();
        return { tile_size.Width * mSizeInTiles.Width, tile_size.Height * mSizeInTiles.Height };
    }
    
    void TileMap::ResizeMap(Sizei size)
    {
        TileRef** new_map = new TileRef*[size.Width];
        for(int i = 0; i < size.Width; i++) 
        {
            new_map[i] = new TileRef[size.Height];
        }

        int smaller_width = mSizeInTiles.Width < size.Width ? mSizeInTiles.Width : size.Width;
        int smaller_height = mSizeInTiles.Height < size.Height ? mSizeInTiles.Height : size.Height;

        for(int i = 0; i < smaller_width; i++)
        {
            for (int j = 0; j < smaller_height; j++)
            {
                new_map[i][j] = mpMap[i][j];
            }
        }

        for(int i = 0; i < mSizeInTiles.Width; i++)
        {
            delete[] mpMap[i];
        }

        delete[] mpMap;
        mSizeInTiles = size;
        mpMap = new_map;
    }

    
    void TileMap::Render(lunarium::IGraphics* g)
    {
        if (!mpMap)
            return;

        // Check the size of the tiles - each tileset should have the same sized tiles for the same map
        Sizei tile_size = (*mpTileSets)[mpMap[0][0].TileSetID]->GetTileSize();
        Sizei map_size_pixels = { tile_size.Width * mSizeInTiles.Width, tile_size.Height * mSizeInTiles.Height };

        // Draw Map
        for (int i = 0; i < mSizeInTiles.Width; i++)
        {
            for (int j = 0; j < mSizeInTiles.Height; j++)
            {
                // If there is no tile here skip this spot
                if (mpMap[i][j].TileIndex.X == -1 || mpMap[i][j].TileIndex.Y == -1)
                    continue;   
                
                TileSet* set = (*mpTileSets)[mpMap[i][j].TileSetID];
                Rectangle dest = Rectangle::MakeFromTopLeft(i * tile_size.Width, j * tile_size.Height, tile_size.Width, tile_size.Height);
                Rectangle src = set->GetTileRect(mpMap[i][j].TileIndex);

                g->DrawImage(*set->GetImage(), src, dest, Color::White());
            }
        }

        // Draw grid
        for (int i = 0; i < mSizeInTiles.Width; i++)
        {
            g->DrawLine(glm::vec2(i * tile_size.Width, 0), glm::vec2(i * tile_size.Width, map_size_pixels.Height), Color::Black(), 1.0f);
        }
        g->DrawLine(glm::vec2(map_size_pixels.Width, 0), glm::vec2(map_size_pixels.Width, map_size_pixels.Height), Color::Black(), 1.0f);

        for (int j = 0; j < mSizeInTiles.Height; j++)
        {
            g->DrawLine(glm::vec2(0, j * tile_size.Height), glm::vec2(map_size_pixels.Width, j * tile_size.Height), Color::Black(), 1.0f);
        }
        g->DrawLine(glm::vec2(0, map_size_pixels.Height), glm::vec2(map_size_pixels.Width, map_size_pixels.Height), Color::Black(), 1.0f);
    }
}}
