//
//  House.cpp
//  Game
//
//  Created by Darvydas on 26/01/2019.
//

#include "cocos2d.h"
#include "Game/GameScene/World/Map/House.hpp"

namespace Game
{
    namespace Map
    {
        using namespace cocos2d;
        
        CHouse::CHouse(int level)
        {
            m_level = 1;
            m_width = 30;
            m_height = 30;
            m_roomCount = 3;
            m_roomWidthMin = 6;
            m_roomWidthMax = 10;
            m_roomHeightMin = 6;
            m_roomHeightMax = 7;
            
            m_vTiles.reserve(m_width * m_height);
            for (int i = 0; i < m_width * m_height; i++)
            {
                m_vTiles.push_back(kTileDead);
            }
            
            generateRooms();
            
            printRoom();
        
            cleanUpMap();
        }
        
        Objects::EGroundTileType CHouse::GetGroundTileType(int x, int y)
        {
            if (getTileValue(x, y) == kTileDead)
            {
                return Objects::EGroundTileType::None;
            }
            else
            {
                // Corner
                if (getTileValue(x - 1, y) == kTileAlive &&
                    getTileValue(x, y + 1) == kTileAlive &&
                    getTileValue(x + 1, y) == kTileDead &&
                    getTileValue(x, y - 1) == kTileDead)
                {
                    return Objects::EGroundTileType::Corner;
                }
                if (getTileValue(x - 1, y) == kTileDead &&
                    getTileValue(x, y + 1) == kTileAlive &&
                    getTileValue(x + 1, y) == kTileAlive &&
                    getTileValue(x, y - 1) == kTileDead)
                {
                    return Objects::EGroundTileType::Corner;
                }
                if (getTileValue(x - 1, y) == kTileDead &&
                    getTileValue(x, y + 1) == kTileDead &&
                    getTileValue(x + 1, y) == kTileAlive &&
                    getTileValue(x, y - 1) == kTileAlive)
                {
                    return Objects::EGroundTileType::Corner;
                }
                if (getTileValue(x - 1, y) == kTileAlive &&
                    getTileValue(x, y + 1) == kTileDead &&
                    getTileValue(x + 1, y) == kTileDead &&
                    getTileValue(x, y - 1) == kTileAlive)
                {
                    return Objects::EGroundTileType::Corner;
                }
                // Side
                if ((getTileValue(x - 1, y) == kTileAlive && getTileValue(x + 1, y) == kTileDead))
                {
                    return Objects::EGroundTileType::Side;
                }
                else if ((getTileValue(x - 1, y) == kTileDead && getTileValue(x + 1, y) == kTileAlive))
                {
                    return Objects::EGroundTileType::Side;
                }
                else if ((getTileValue(x, y - 1) == kTileDead && getTileValue(x, y + 1) == kTileAlive))
                {
                    return Objects::EGroundTileType::Side;
                }
                else if ((getTileValue(x, y - 1) == kTileAlive && getTileValue(x, y + 1) == kTileDead))
                {
                    return Objects::EGroundTileType::Side;
                }
                // Center
                if (getTileValue(x - 1, y) == kTileAlive &&
                    getTileValue(x, y + 1) == kTileAlive &&
                    getTileValue(x + 1, y) == kTileAlive &&
                    getTileValue(x, y - 1) == kTileAlive)
                {
                    return Objects::EGroundTileType::Center;
                }
            }
			return Objects::EGroundTileType::None;
        }
        
        std::pair<int, int> CHouse::getEmptyPosition(std::string strType, int width, int height)
        {
            int randomX = -1;
            int randomY = -1;
            
            bool bLoop = true;
            
            while (bLoop)
            {
                randomX = cocos2d::random(1, m_width - 1);
                randomY = cocos2d::random(1, m_height - 1);
                
                if (strType == "OnWall")
                {
                    if (getTileValue(randomX, randomY) == kTileDead && getTileValue(randomX, randomY - 1) != kTileDead && getTileValue(randomX + 1, randomY) == kTileDead && getTileValue(randomX + 1, randomY - 1) != kTileDead)
                    {
                        bLoop = false;
                    }
                }
                else if (strType == "NearWall")
                {
                    if (getTileValue(randomX, randomY) == kTileAlive && getTileValue(randomX, randomY + 1) == kTileDead)
                    {
                        bLoop = false;
                    }
                }
                else if (strType == "OnGround")
                {
                    int blockingTiles = 0;
                    
                    for (int xx = randomX - 1; xx < randomX + width; xx++)
                    {
                        for (int yy = randomY - 1; yy < randomY + height; yy++)
                        {
                            if (getTileValue(xx, yy) != kTileAlive)
                            {
                                blockingTiles++;
                            }
                        }
                    }
                    if (blockingTiles == 0)
                    {
                        bLoop = false;
                    }
                }
                else
                {
                    if (IsItGround(randomX, randomY))
                    {
                        bLoop = false;
                    }
                    for (int i = 1; i < width; i++)
                    {
                        if (getTileValue(randomX + i, randomY) == kTileDead)
                        {
                            bLoop = true;
                        }
                    }
                    for (int i = 1; i < height; i++)
                    {
                        if (getTileValue(randomX, randomY + i) == kTileDead)
                        {
                            bLoop = true;
                        }
                    }
                }
            }
            return std::make_pair(randomX, randomY);
        }
        
        bool CHouse::IsItGround(int x, int y)
        {
			int index = x + y * m_width;
			if (index >= 900 || index < 0)
			{
				int i = 0;
				return false;
			}
            if (m_vTiles[x + y * m_width] == kTileAlive)
            {
                return true;
            }
            return false;
        }
        
        int CHouse::getWidth()
        {
            return m_width;
        }
        
        int CHouse::getHeight()
        {
            return m_height;
        }
        
        bool CHouse::isOutOfRange(int x, int y, int width, int height)
        {
            if (x + width >= m_width || y + height >= m_height)
            {
                return true;
            }
            return false;
        }
        
        void CHouse::setTileValue(int x, int y, char c)
        {
            m_vTiles[x + y * m_width] = c;
        }
        
        char CHouse::getTileValue(int x, int y)
        {
			int index = x + y * m_width;
			if (index >= 900 || index < 0)
			{
				int i = 0;
				return kTileDead;
			}
            return m_vTiles[x + y * m_width];
        }
        
        bool CHouse::isAllTilesEmpty(int x, int y, int width, int height)
        {
            for (int xx = x; xx < x + width; xx++)
            {
                for (int yy = y; yy < y + height - 1; yy++)
                {
					int index = xx + yy * m_width;
					if (index >= 900 || index < 0)
					{
						int i = 0;
					}
                    if (m_vTiles[xx + yy * m_width] == kTileAlive)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
        
        bool CHouse::tileExists(int x, int y)
        {
            if (x < 0 || y < 0 || x >= m_width || y >= m_height)
            {
                return false;
            }
            return true;
        }
        
        bool CHouse::isTouching(int x, int y, int width, int height)
        {
            for (int xx = x - 1; xx < x + width + 1; xx++)
            {
                for (int yy = y - 1; yy < y + height + 1; yy++)
                {
                    if ((xx == x - 1 && yy == y - 1) ||
                        (xx == x - 1 && yy == y + height) ||
                        (xx == x - width && yy == y - 1) ||
                        (xx == x - width && yy == y + height))
                    {
                        continue;
                    }
                    
                    if (tileExists(xx, yy))
                    {
						int index = xx + yy * m_width;
						if (index >= 900 || index < 0)
						{
							int i = 0;
						}

						if (m_vTiles[xx + yy * m_width] == kTileAlive)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        
        bool CHouse::isSeperatedByWall(int x, int y, int witdh, int height)
        {
			return false;
        }
        
        void CHouse::placeRoom(int x, int y, int width, int height)
        {
            for (int xx = x; xx < x + width; xx++)
            {
                for (int yy = y; yy < y + height; yy++)
                {
                    log("CHouse::placeRoom (%d;%d)", xx, yy);

					int index = xx + yy * m_width;
					cocos2d:log("IND %d\n", index);
					if (index >= 900 || index < 0)
					{
						int i = 0;
					}

                    m_vTiles[xx + yy * m_width] = kTileAlive;
                }
            }
        }
        
        void CHouse::generateRooms()
        {
            bool bInitial = true;
            
            int roomsPlaced = 0;
            
            while (roomsPlaced < m_roomCount)
            {
                int randomX = cocos2d::random(0, m_width);
                int randomY = cocos2d::random(0, m_height);
                int randomWidth = cocos2d::random(m_roomWidthMin, m_roomWidthMax);
                int randomHeight = cocos2d::random(m_roomHeightMin, m_roomHeightMax);
                
                if (!isOutOfRange(randomX, randomY, randomWidth, randomHeight) &&
					isAllTilesEmpty(randomX, randomY, randomWidth, randomHeight))
                {
                    if (isTouching(randomX, randomY, randomWidth, randomHeight) || bInitial == true)
                    {
                        roomsPlaced++;
                        bInitial = false;
                        placeRoom(randomX, randomY, randomWidth, randomHeight);
                    }
                }
            }
        }
        
        void CHouse::cleanUpMap()
        {
            for (int y = 1; y < m_height - 1; y++)
            {
                for (int x = 1; x < m_width - 1; x++)
                {
                    if (getTileValue(x, y) == kTileDead && getTileValue(x, y - 1) == kTileAlive && getTileValue(x, y + 1) == kTileAlive)
                    {
                        setTileValue(x, y, kTileAlive);
                    }
                }
            }
        }
        
        void CHouse::printRoom()
        {
            for (int y = 0; y < m_height; y++)
            {
                for (int x = 0; x < m_width; x++)
                {
                    char tile = m_vTiles[x + y * m_height];
                    if (tile == kTileAlive)
                    {
                        printf("#");
                    }
                    else
                    {
                        printf("-");
                    }
                }
                log("");
            }
            log("");
        }
    }
}
