#include <game/agame/background.hpp>
#include <window/window.hpp>
#include <object/camera.hpp>
#include <algorithm>

namespace Game::AGame {
    void Background::start() {
        mEnemyTex = std::make_shared<Game::Renderer::Texture>("../resources/l3enemy.png", SDL_GetRenderer(Window::Window::getSDLWindowBackend()), "enemyTex");
        mTrashTex = std::make_shared<Game::Renderer::Texture>("../resources/l3trash.png", SDL_GetRenderer(Window::Window::getSDLWindowBackend()), "trashTex");
        GameManager::setSharedData("enemyActiveCount", 0);

        mZIndex = -1; // Ensure background renders behind other entities
        mTex->setTiled(true); // Set the background texture to be tiled
        mTiledScale = 0.5f;
        SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &mW, &mH);

        mTransform.scaleX *= 10.f;
        mTransform.scaleY *= 10.f;

        mTransform.x -= mTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
        mTransform.y -= mTex->getHeight() * mTransform.adjustedScaleY() / 2.f;

        LOG("W: " << mW << " H: " << mH);

        mTransform.x = mW / 2.f - (mW / 3.f);
        mTransform.y = -mH;
    }

    void Background::update(float deltaTime) {
        mEnemySpawnTimer += deltaTime;

        int cnt = GameManager::getSharedData<int>("enemyActiveCount");
        if (mEnemySpawnTimer >= mTimeToSpawn && cnt < 5) {
            mEnemySpawnTimer = 0.f; // RESET
            GameManager::setSharedData("enemyActiveCount", cnt + 1);
            // Spawn Enemy on grass
            Object::Transform tS;
            tS.scaleY = 7.f;
            tS.scaleX = 7.f;
            tS.rotation = 0.f;

            float camX, camY;
            Object::Camera::getInstance().getPosition(camX, camY);

            const float halfEnemyW = mEnemyTex->getWidth() * tS.adjustedScaleX() / 2.f;
            const float halfEnemyH = mEnemyTex->getHeight() * tS.adjustedScaleY() / 2.f;

            const float viewLeft = camX - (mW / 2.f);
            const float viewRight = camX + (mW / 2.f);
            const float viewTop = camY - (mH / 2.f);
            const float viewBottom = camY + (mH / 2.f);

            // Right 1/3 of the currently visible screen, in world coordinates.
            int spawnMinX = static_cast<int>(viewLeft + (2.f * mW / 3.f) + halfEnemyW);
            int spawnMaxX = static_cast<int>(viewRight - halfEnemyW - 25.f);
            int spawnMinY = static_cast<int>(viewTop + halfEnemyH + 100.f);
            int spawnMaxY = static_cast<int>(viewBottom - halfEnemyH - 100.f);

            // Safety for tiny windows / huge sprites.
            if (spawnMinX > spawnMaxX) spawnMinX = spawnMaxX = static_cast<int>(camX);
            if (spawnMinY > spawnMaxY) spawnMinY = spawnMaxY = static_cast<int>(camY);

            tS.x = static_cast<float>(Utils::getUtils().rirng32(spawnMinX, spawnMaxX));
            tS.y = static_cast<float>(Utils::getUtils().rirng32(spawnMinY, spawnMaxY));
            GameManager::instantiateEntity(std::make_unique<AGame::Enemy>("Enemy" + std::to_string(cnt + 1), mEnemyTex, tS));

            // Spawn Trash at shoreline
            tS.scaleX = 5.5f;
            tS.scaleY = 5.5f;
            tS.rotation = 0.f;
            tS.x = mTransform.x - 75.f;
            tS.y = static_cast<float>(Utils::getUtils().rirng32(spawnMinY, spawnMaxY));
            GameManager::instantiateEntity(std::make_unique<AGame::Trash>("Trash" + std::to_string(cnt + 1), mTrashTex, tS));
        }

        /*const bool* state = SDL_GetKeyboardState(nullptr);
        if (state[SDL_SCANCODE_P]) {
            mTransform.scaleX *= 2.f;
            mTransform.scaleY *= 2.f;
        }
        if (state[SDL_SCANCODE_L]) {
            mTransform.scaleX *= 0.5f;
            mTransform.scaleY *= 0.5f;
        }*/
        //mTransform.rotation += 1.f; // Rotate clockwise for testing
        //mTransform.scaleX = 1.f + 1.f * std::sin(RUNNING_TIME() / 0.5f); // Pulsate scale for testing
        //mTransform.scaleY = 1.f + 0.5f * std::cos(RUNNING_TIME() / 0.5f); // Pulsate scale for testing

        //Object::Camera::getInstance().move(1.f, 0.f);
    }

    void Background::onWindowResized(int newWidth, int newHeight) {
        mW = newWidth;
        mH = newHeight;
    }
}