#include <random>
#include <iostream>
#include "../headers/Plansza.h"
#include "../headers/ObjectItem.hpp"

Plansza::Plansza(unsigned int windowHeight, unsigned int windowWidth, sf::RenderWindow *mainWindow)
: background("../assets/img/background/background.png", 2.0f),
ship(static_cast<int>(mainWindow->getSize().x) / 2, static_cast<int>(mainWindow->getSize().y) - 100, "../assets/ship/Dreadnought-Base.png")
{

    window = mainWindow;
    size.height = static_cast<int>(windowHeight);
    size.width = static_cast<int>(windowWidth);

    ship.setMovingSpeed(8);
    ship.setFirerate(200);

    audioManager.loadBackgroundMusic("../assets/music/background.ogg");
    audioManager.playBackgroundMusic();

    audioManager.loadSoundEffect("shoot", "../assets/sounds/shoot.ogg");
    audioManager.loadSoundEffect("shoot_alt", "../assets/sounds/shoot_alt.ogg");
    audioManager.loadSoundEffect("fail", "../assets/sounds/fail.mp3");

    meteorTexture1.loadFromFile("../assets/img/meteors/meteor-1.png");
    meteorTexture2.loadFromFile("../assets/img/meteors/meteor-2.png");

    heartTexture.loadFromFile("../assets/img/hearts/heart.png");

    meteorSpawnClock.restart();
}


void Plansza::update() {
// tło
        background.update();
        background.draw(*window);

        // poruszanie się statkiem
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
            if(ship.getPosition().x > 50) {
                ship.moveLeft();
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
            if(ship.getPosition().y > 80) {
                ship.moveUp();
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
            if(ship.getPosition().y < 720) {
                ship.moveDown();
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
            if(ship.getPosition().x < 550) {
                ship.moveRight();
            }
        }

        // TODO: Przenieść obiekt dźwięku wewnątrz klasy Bullet
        if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
            ship.shoot();
            audioManager.playSoundEffect("shoot", 70.f); // Odtworzenie dźwięku wystrzału
        }
        if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
            ship.alternate_shoot();
            audioManager.playSoundEffect("shoot_alt", 70.f); // Odtworzenie dźwięku dla alternatywnego strzału
        }

        // generowanie nowego meteoru
        spawn_meteor();
        spawn_hearts();


        // utrzymanie meteorów i pocisków w ruchu
        for (auto& meteor : meteors) {
            meteor.update();
            window->draw(meteor.getSprite());
        }

        for (auto& heart : hearts) {
            heart.update();
            window->draw(heart.getSprite());
        }

        for (auto& bullet : ship.getBullets()) {
            bullet.update();
            window->draw(bullet.getSprite());
        }

        for (auto& rocket : ship.getRockets()) {
            rocket.update();
            window->draw(rocket.getSprite());
        }

        // Sprawdzenie czy meteory i pociski są poza granicami ekranu
        update_meteors();
        update_hearts();
        ship.updateBullets();

        window->draw(ship.getSprite());


        // trochę dziwny sposób ale jednak działa
        for (auto& meteor : getMeteors()) {
            if(ship.getSprite().getGlobalBounds().intersects(meteor.getSprite().getGlobalBounds())) {
                std::cout << "You lost the game!\n";
                sf::RenderWindow errorWindow(sf::VideoMode(350, 200), "The end");
                sf::Font font;
                if (!font.loadFromFile("../assets/fonts/arial.ttf")) {
                    std::cerr << "Error loading font\n";
                    exit(-500);
                }
                sf::Text text("Your ship is destroyed!", font, 24);
                text.setFillColor(sf::Color::Red);
                text.setPosition(50, 80);

                // zatrzymanie muzyki i odtworzenie dźwięku przegranej
                audioManager.playSoundEffect("fail", 70.f);
                audioManager.stopBackgroundMusic();
                sf::Event event{};
                while (errorWindow.isOpen()) {
                    while (errorWindow.pollEvent(event)) {
                        if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
                            errorWindow.close();
                            window->close();
                            exit(-2);
                        }
                    }
                    errorWindow.clear();
                    errorWindow.draw(text);
                    errorWindow.display();
                }
            }
        }

        for (auto meteorIt = getMeteors().begin(); meteorIt != getMeteors().end(); ) {
            bool meteorHit = false;
            for (auto rocketIt = ship.getBullets().begin(); rocketIt != ship.getBullets().end(); ) {
                if (meteorIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) {
                    ship.getBullets().erase(rocketIt);
                    meteorIt = getMeteors().erase(meteorIt);
                    meteorHit = true;
                    break;
                } else {
                    ++rocketIt;
                }
            }
            if (!meteorHit) {
                ++meteorIt;
            }
        }

        for (auto meteorIt = getMeteors().begin(); meteorIt != getMeteors().end(); ) {
            bool meteorHit = false;
            for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end(); ) {
                if (meteorIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) {
                    ship.getRockets().erase(rocketIt);
                    meteorIt = getMeteors().erase(meteorIt);
                    meteorHit = true;
                    break;
                } else {
                    ++rocketIt;
                }
            }
            if (!meteorHit) {
                ++meteorIt;
            }
        }
}

// Meteor-related niżej

void Plansza::spawn_meteor() {
    if (meteorSpawnClock.getElapsedTime().asSeconds() > rand() % 10 + 1) { // randomowy spawn meteorytów od 10 do 1 sekundy
        if (meteors.size() < 5) { // jeśli jest mniej niż 5 meteorów na planszy
            if(rand() % 2 == 1) {
                meteors.emplace_back(RandomNumberGenerator::getRandomNumber(50,499), -100, meteorTexture2);
            } else {
                meteors.emplace_back(RandomNumberGenerator::getRandomNumber(50,499), -100, meteorTexture1);
            }
        }
        meteorSpawnClock.restart();
    }
}

void Plansza::spawn_hearts() {
    if (heartSpawnClock.getElapsedTime().asSeconds() > rand() % 10 + 1) { // randomowy spawn meteorytów od 10 do 1 sekundy
        if (hearts.size() < 5) { // jeśli jest mniej niż 5 meteorów na planszy
             hearts.emplace_back(RandomNumberGenerator::getRandomNumber(50, 499), -100, heartTexture);
        }
        heartSpawnClock.restart();
    }
}

void Plansza::update_meteors() {
    // usuwanie meteorów które wyleciały poza ekran
    for (auto& meteor : meteors) {
        if(meteor.getStatus()) {
            meteors.erase(meteors.begin());
        }
    }
}

void Plansza::update_hearts() {
    // usuwanie serduszek które wyleciały poza ekran
    for (auto& heart : hearts) {
        if(heart.getStatus()) {
            hearts.erase(hearts.begin());
        }
    }
}

Size Plansza::getSize() {
    return size;
}

std::vector<Meteor> &Plansza::getMeteors() {
    return meteors;
}



