#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <cmath>

class Player {

    public:
        float xpos;
        float ypos;

        float speed;


};

class Target {

    public:
        std::string name;
        float xpos;
        float ypos;

        std::string enemy;


};

bool Up;
bool Down;
bool Left;
bool Right;

int game_over(sf::RenderWindow& window, int score)
{


    sf::Font font;
    if (!font.openFromFile("data/fonts/arial.ttf")) {
        std::cout << "Font not loaded";
    }
    
    sf::Text text(font);
    text.setString("Game Over");
    text.setCharacterSize(48);
    text.setFillColor(sf::Color::White);
    text.setPosition({350.f, 400.f});

    sf::Text scoretext(font);
    scoretext.setString(std::string("Score:") + std::to_string(score));
    scoretext.setCharacterSize(24);
    scoretext.setFillColor(sf::Color::White);
    scoretext.setPosition({420.f, 470.f});


    while (window.isOpen())
    {
        while (std::optional<sf::Event> event = window.pollEvent()) {
            if (event->is<sf::Event::Closed>()) {
                window.close();
            }
        }
        window.clear();
        window.draw(scoretext);
        window.draw(text);
        window.display();
        
    }

    return 0;
}


int main()
{

    

    sf::RenderWindow window(sf::VideoMode({1000, 1000}), "Tag");
    window.setFramerateLimit(60);

    sf::Font font;
    if (!font.openFromFile("data/fonts/arial.ttf")) {
        std::cout << "Font not loaded";
    }
    
    sf::Text text(font);
    text.setString("Score:");
    text.setCharacterSize(24);
    text.setFillColor(sf::Color::White);
    text.setPosition({0.f, 0.f});

    sf::Text timer(font);
    timer.setString("Time Left:");
    timer.setCharacterSize(24);
    timer.setFillColor(sf::Color::White);
    timer.setPosition({900.f, 0.f});

    

    Player P1;

    P1.xpos = 500;
    P1.ypos = 500;
    P1.speed = 4;

    sf::RectangleShape player({40.f, 40.f});
    player.setFillColor(sf::Color(150, 50, 250));

    Target T1;

    int outerBound = 900;

    T1.xpos = 50 + std::rand() % outerBound;
    T1.ypos = 50 + std::rand() % outerBound;
    T1.enemy = false;

    Target T2;

    T2.xpos = 50 + std::rand() % outerBound;
    T2.ypos = 50 + std::rand() % outerBound;
    T2.enemy = false;


    Target T3;

    T3.xpos = 50 + std::rand() % outerBound;
    T3.ypos = 50 + std::rand() % outerBound;
    T3.enemy = false;

    Target T4;

    T4.xpos = 50 + std::rand() % outerBound;
    T4.ypos = 50 + std::rand() % outerBound;
    T4.enemy = false;

    Target E1;

    E1.xpos = 50 + std::rand() % outerBound;
    E1.ypos = 50 + std::rand() % outerBound;
    E1.enemy = true;


    sf::RectangleShape target({40.f, 40.f});
    target.setFillColor(sf::Color(20, 100, 250));

    sf::RectangleShape target2({40.f, 40.f});
    target2.setFillColor(sf::Color(20, 100, 250));

    sf::RectangleShape target3({40.f, 40.f});
    target3.setFillColor(sf::Color(20, 100, 250));

    sf::RectangleShape target4({40.f, 40.f});
    target4.setFillColor(sf::Color(20, 100, 250));

    sf::RectangleShape enemy({40.f, 40.f});
    enemy.setFillColor(sf::Color(255, 0, 0));

    int timeleft = 0;
    int time = 1800;
    int score = 0;


    while (window.isOpen())
    {

        timeleft++;

        timer.setString(std::string("Time:") + std::to_string(static_cast<int>(std::floor((time - timeleft) / 60))));
        //std::cout << std::string("Time:") + std::to_string(std::floor((time - timeleft) / 60)) << std::endl;
        text.setString(std::string("Score:") + std::to_string(score));

        if((time - timeleft) == 0)
        {
            game_over(window, score);
        }


        while (std::optional<sf::Event> event = window.pollEvent()) {
            if (event->is<sf::Event::Closed>()) {
                window.close();
            }
            
            if (const auto* keyReleased = event->getIf<sf::Event::KeyReleased>()) {
                if (keyReleased->code == sf::Keyboard::Key::Up)
                    Up = false;
                if (keyReleased->code == sf::Keyboard::Key::Down)
                    Down = false;
                if (keyReleased->code == sf::Keyboard::Key::Right)
                    Right = false;
                if (keyReleased->code == sf::Keyboard::Key::Left)
                    Left = false;
            }
            
            if (const auto* keyPressed = event->getIf<sf::Event::KeyPressed>()) {
                if (keyPressed->code == sf::Keyboard::Key::Up)
                    Up = true;
                if (keyPressed->code == sf::Keyboard::Key::Down)
                    Down = true;
                if (keyPressed->code == sf::Keyboard::Key::Right)
                    Right = true;
                if (keyPressed->code == sf::Keyboard::Key::Left)
                    Left = true;
            }
        }
        //Movement handling

        if(Up == true)
            P1.ypos = P1.ypos - P1.speed;
        if(Down == true)
            P1.ypos = P1.ypos + P1.speed;
        if(Right == true)
            P1.xpos = P1.xpos + P1.speed;
        if(Left == true)
            P1.xpos = P1.xpos - P1.speed;

        //Set positions
        player.setPosition({P1.xpos, P1.ypos});
        target.setPosition({T1.xpos, T1.ypos});
        target2.setPosition({T2.xpos, T2.ypos});
        target3.setPosition({T3.xpos, T3.ypos});
        target4.setPosition({T4.xpos, T4.ypos});
        enemy.setPosition({E1.xpos, E1.ypos});

        //Collision

        sf::FloatRect PlayerBox = player.getGlobalBounds();
        sf::FloatRect TargetBox = target.getGlobalBounds();
        sf::FloatRect Target2Box = target2.getGlobalBounds();
        sf::FloatRect Target3Box = target3.getGlobalBounds();
        sf::FloatRect Target4Box = target4.getGlobalBounds();
        sf::FloatRect EnemyBox = enemy.getGlobalBounds();

        if (const std::optional intersection = PlayerBox.findIntersection(TargetBox)){
            
            T1.xpos = 50 + std::rand() % outerBound;
            T1.ypos = 50 + std::rand() % outerBound;
            score++;
        }

        if (const std::optional intersection = PlayerBox.findIntersection(Target2Box)){
            
            T2.xpos = 50 + std::rand() % outerBound;
            T2.ypos = 50 + std::rand() % outerBound;
            score++;
        }

        if (const std::optional intersection = PlayerBox.findIntersection(Target3Box)){
            
            T3.xpos = 50 + std::rand() % outerBound;
            T3.ypos = 50 + std::rand() % outerBound;
            score++;
        }

        if (const std::optional intersection = PlayerBox.findIntersection(Target4Box)){
            
            T4.xpos = 50 + std::rand() % outerBound;
            T4.ypos = 50 + std::rand() % outerBound;
            score++;
        }


        if (static_cast<int>(std::floor((time - timeleft) % 300) == 0)){
            
            E1.xpos = 50 + std::rand() % outerBound;
            E1.ypos = 50 + std::rand() % outerBound;

            while(const std::optional intersection = PlayerBox.findIntersection(EnemyBox)){

            E1.xpos = 50 + std::rand() % outerBound;
            E1.ypos = 50 + std::rand() % outerBound;

            }
        }

        if (const std::optional intersection = PlayerBox.findIntersection(EnemyBox)){
            
            game_over(window, score);
        }

        

        //Rendering
        window.clear();
        window.draw(player);
        window.draw(target);
        window.draw(target2);
        window.draw(target3);
        window.draw(target4);
        window.draw(enemy);
        window.draw(text);
        window.draw(timer);

        window.display();
            
    }

    return 0;
}