#include <functional>
#include <iostream>
#include <memory>

#include "Battle/BattleField.h"
#include "Core/BasicPrintVisitor.h"
#include "Core/PrettyPrintVisitor.h"
#include "Core/Time.h"
#include "Player/Enemy.h"
#include "Player/EnemyEasyDifficultLvlStrategy.h"
#include "Player/EnemyHardDifficultLvlStrategy.h"
#include "Player/RealPlayer.h"
#include "Ship/AlcoholFactory.h"
#include "Ship/Cargo.h"
#include "Ship/CargoDamageVisitor.h"
#include "Ship/FruitFactory.h"
#include "Ship/ItemFactory.h"
#include "Ship/Ship.h"
#include "Ship/ShipBuilder.h"
#include "Ship/ShipEasyDifficultLvlStrategy.h"
#include "Ship/ShipHardDifficultLvlStrategy.h"
#include "Ship/ShipJsonBuilder.h"
#include "Store/Store.h"

int main() {
    Time time;

    auto ship = ShipBuilder()
                    .setTime(&time)
                    .setName("Black Widow")
                    .setCapacity(1000)
                    .setCrew(40)
                    .setStrategy(std::make_unique<ShipHardDifficultLvlStrategy>())
                    .setVisitor(std::make_unique<PrettyPrintVisitor>())
                    .setArmor(100)
                    .setDurability(1000)
                    .build();
    ship->load(AlcoholFactory().create(300, 40, Alcohol::Type::Spiced));
    ship->load(FruitFactory().create(200, 15));
    ship->load(FruitFactory().create(150, 15));
    ship->load(ItemFactory().create(250, Item::Type::Epic));
    ship->printCargo();
    RealPlayer user("Mateusz", std::move(ship));

    Enemy enemy("Enemy1",
                ShipJsonBuilder("../ships.json").buildGaleon(&time, "Queens Anne revenge"),
                std::make_unique<EnemyHardDifficultLvlStrategy>(),
                CargoDamageVisitor{});

    BattleField battefield{&user, &enemy};
    while (true) {
        for (auto* player : battefield.players()) {
            std::cout << "-------------------------------------------------------------------\n";
            std::cout << "Player HP: " << user.getShip().durability() << "   ARMOR: " << user.getShip().armor() << "  |  ";
            std::cout << "Enemy HP: " << enemy.getShip().durability() << "   ARMOR: " << enemy.getShip().armor() << '\n';
            std::cout << "-------------------------------------------------------------------\n";
            for (size_t i = 0; i < 3; ++i) {
                const auto status = player->makeAction(battefield);
                if (status == Action::Status::Escaped || status == Action::Status::Defeated) {
                    return 0;
                }
            }
        }
    }
}
