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

#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 "Ship/Cargo.h"
#include "Ship/CargoDamageVisitor.h"
#include "Ship/Ship.h"
#include "Ship/ShipEasyDifficultLvlStrategy.h"
#include "Ship/ShipHardDifficultLvlStrategy.h"
#include "Store/Store.h"

int main() {
    Time time;
    std::vector<std::unique_ptr<Cargo>> cargoes;
    cargoes.push_back(std::make_unique<Alcohol>(1'000));
    cargoes.push_back(std::make_unique<Fruit>(1'000));
    cargoes.push_back(std::make_unique<Item>(1'000));
    auto store = std::unique_ptr<Store, std::function<void(Store*)>>(
        [&cargoes, &time]() {
         auto* store = new Store(std::move(cargoes), std::make_unique<BasicPrintVisitor>());
         try {
            time.attach(store);
         } catch (...) {
            abort();
         }
         return store; }(),
        [&time](Store* store) {
            time.detach(store);
            delete store;
        });

    Ship ship(&time, std::make_unique<ShipHardDifficultLvlStrategy>(), "Black Widow", 1000, 40, std::make_unique<PrettyPrintVisitor>());
    ship.load(std::make_unique<Alcohol>(300));
    ship.load(std::make_unique<Fruit>(200));
    ship.load(std::make_unique<Fruit>(150));

    std::cout << "Ship\n";
    ship.printCargo();
    std::cout << "\nStore\n";
    store->printCargo();

    std::cout << "\n\n****************************************************\n";
    auto ship2 = std::make_unique<Ship>(&time, std::make_unique<ShipHardDifficultLvlStrategy>(), "Queens Anne revenge", 1000, 40, std::make_unique<PrettyPrintVisitor>());
    Enemy enemy("Enemy1", std::move(ship2), std::make_unique<EnemyHardDifficultLvlStrategy>(), CargoDamageVisitor{});

    for (int i = 0; i < 5; ++i) {
        enemy.attack(ship);
        ship.printCargo();
    }
}
