//
//  World.cpp
//  Game
//
//  Created by Darvydas on 24/01/2019.
//
#include "Config/Config.hpp"
#include "Game/GameScene/World/World.hpp"
#include "Game/GameScene/World/Player.hpp"

using namespace cocos2d;

namespace Game
{
    CWorld *CWorld::create(cocos2d::Scene* pcGameScene, CHUD* hud)
    {
        CWorld *world = new CWorld;
        
        world->m_pcGameScene = pcGameScene;
        
        if (world->init())
        {
			world->setTextureRect(Rect(0, 0, CConfig::m_ResoliutionX, CConfig::m_ResoliutionY));
            world->autorelease();
            
            world->setColor(Color3B::BLACK);
            world->createVisualElements(hud);
            
            world->scheduleUpdate();
            
            return world;
        }
        CC_SAFE_DELETE(world);
        return NULL;
    }
    
    CPlayer* CWorld::getPlayer()
    {
        return m_pcPlayer;
    }
    
    void CWorld::update(const float dt)
    {
        centerCameraOnPlayer();
    }
    
    void CWorld::centerCameraOnPlayer()
    {
        this->setPosition(Point(-m_pcPlayer->getPosition().x + this->getContentSize().width,
                                -m_pcPlayer->getPosition().y + this->getContentSize().height));
    }
    
    void CWorld::createVisualElements(CHUD* hud)
    {
        float dimension = CConfig::m_fTileDimension;

        createHouseElements();

        m_pcPlayer = CPlayer::create(m_pcHouse, Size(CConfig::m_fTileDimension, CConfig::m_fTileDimension), hud);

        auto emptyPosition = m_pcHouse->getEmptyPosition("");
        
        m_pcPlayer->setPosition(Point(dimension * 0.5f + dimension * float(emptyPosition.first), dimension * 0.5f + dimension * float(emptyPosition.second)));
        
        this->addChild(m_pcPlayer, 300);
    }
    
    void CWorld::interact()
    {
        for (Objects::CInteractiveObject* obj : m_vInteractiveObjects)
        {
            auto distance = obj->getPosition().distance(m_pcPlayer->getPosition());
            if (distance < CConfig::m_fTileDimension * 2.0f)
            {
                m_pcDialogue = Dialogue::create(m_pcPlayer, obj);
                this->addChild(m_pcDialogue, 999);
                return;
            }
        }
    }
    
    void CWorld::createHouseElements()
    {
        m_pcHouse = new Map::CHouse(1);
        
        /* Ground */
        
        std::vector<std::string> allGroundImages =
        {
            "tilecarpet1.png",
            "tilecarpet1a.png",
            "tilecarpet1b.png",
            "tilecarpet2.png",
            "tilecarpet2a.png",
            "tilecarpet2b.png",
            "tilecarpet3.png",
            "tilecarpet3b.png",
            "tilecarpet3c.png",
            "tilecarpet3d.png",
        };
        int randomGroundTile = cocos2d::random(0, int(allGroundImages.size() - 1));
        
        float dimension = CConfig::m_fTileDimension;
        
        for (int x = 0; x < m_pcHouse->getWidth(); x++)
        {
            for (int y = 0; y < m_pcHouse->getHeight(); y++)
            {
                if (m_pcHouse->IsItGround(x, y))
                {
                    auto ground = Objects::CTile::create(this, allGroundImages[randomGroundTile]);
                    
                    ground->setPosition(Point(dimension * 0.5f + dimension * float(x), dimension * 0.5f + dimension * float(y)));
                    
                    this->addChild(ground, 200);
                }
            }
        }
        
        /* Create walls */
        
        std::vector<std::string> allImages =
        {
            "wall1.png",
            "wall2.png",
            "wall2a.png",
            "wall2b.png",
            "wall3.png",
            "wall4.png",
            "wall5.png",
        };
        int randomWallTile = cocos2d::random(0, int(allImages.size() - 1));
        
        for (int x = 0; x < m_pcHouse->getWidth(); x++)
        {
            for (int y = 0; y < m_pcHouse->getHeight(); y++)
            {
				int indexY = y - 1;

                if (!m_pcHouse->IsItGround(x, y) && m_pcHouse->getTileValue(x, indexY < 0 ? 0 : indexY) == kTileAlive)
                {
                    auto ground = Objects::CTile::create(this, allImages[randomWallTile]);
                    
                    ground->setPosition(Point(dimension * 0.5f + dimension * float(x), dimension * 0.5f + dimension * float(y)));
                    
                    this->addChild(ground, 220);
                }
            }
        }
        
        /* Interactive objects */
        
        json::CManager* manager = json::CManager::getInstance();
        
        manager->openFile("items.json");
        
        rapidjson::Document& document = *manager->getOpenedDocument();
        
        if (document.HasMember("Object"))
        {
            const rapidjson::Value& array = document["Object"];  // you are missing this
            if (array.IsArray())
            {
                for (rapidjson::SizeType i = 0; i < array.Size(); i++)
                {
                    const rapidjson::Value& object = array[i];
                    
                    const rapidjson::Value& id = object["ID"];
                    log("%s", id.GetString());
                    
                    const rapidjson::Value& SizeX = object["SizeX"];
                    const rapidjson::Value& SizeY = object["SizeY"];
                    int x = SizeX.GetInt();
                    int y = SizeY.GetInt();
                    
                    const rapidjson::Value& type = object["Type"];
                    
                    for (std::string strName : Game::World::CConfig::getInstance()->getInteractiveObjects(1))
                    {
                        if (strName == id.GetString())
                        {
                            auto interactiveObject = Objects::CInteractiveObject::create(object);
                            auto emptyPos = m_pcHouse->getEmptyPosition(type.GetString(), x, y);

                            for (int i = 0; i < x; i++)
                            {
                                m_pcHouse->setTileValue(emptyPos.first + i, emptyPos.second, kTileObject);
                            }
                            for (int i = 0; i < y; i++)
                            {
                                m_pcHouse->setTileValue(emptyPos.first, emptyPos.second + i, kTileObject);
                            }
                            
                            interactiveObject->setPosition(Point(dimension * 0.5f + dimension * emptyPos.first + dimension * 0.5f * (x - 1), dimension * 0.5f + dimension * emptyPos.second + dimension * 0.5 * (y - 1)));
                            
                            this->addChild(interactiveObject, 300);
                            m_vInteractiveObjects.push_back(interactiveObject);
                        }
                    }
                }
            }
        }
    }
}





