#include <iostream>
#include <sstream>
#include <type_traits>
#include "catch.hpp"
#include "code.hpp"

/*
TEST_CASE("Machine0") {
    CHECK(0 == Machine::getCompteur());
} */

TEST_CASE("Presentation") {
    std::stringstream ss;
    std::cout << "Lisez bien le sujet avant de commencer" << std::endl;
    std::cout << "Ce test est à supprimer et ne compte pas :-) Bon courage" << std::endl;
    REQUIRE(0 == 1);
}

/*
TEST_CASE("Object1") {
    const char * nom     = "alcor";
    
    Objet o(nom);

    CHECK( nom     == o.getNom());
}

TEST_CASE("Object2") {
    const char * nom     = "actarus";
    
    const Objet o(nom);

    CHECK( nom     == o.getNom());
}

TEST_CASE("Pilote1") {
    const char * nom     = "venusia";
    std::stringstream ss;

    const Pilote p(nom);

    ss << p;

    CHECK(nom == ss.str());
}


TEST_CASE("Impossible1") {
    ImpossibleException e;
    REQUIRE(std::string("operation impossible") == e.what());
}

TEST_CASE("Machine1") {
    Machine * robot = new Robot("mazinger");

    CHECK(true == std::is_abstract_v<Machine>);
    
    delete robot;
}
 
TEST_CASE("Robot1") {
    Machine * robot = new Robot("mazinger");

    REQUIRE("mazinger" == robot->getNom());
    REQUIRE(nullptr == robot->getPilote());
    REQUIRE(false == robot->getAutomatique());
    
    delete robot;
}

TEST_CASE("Robot2") {
    Pilote pilote("actarus");
    Machine * robot = new Robot("goldorak");
    robot->setPilote(&pilote);
    std::stringstream ss;
    
    ss << robot->bouge();

    REQUIRE("actarus pilote goldorak qui marche" == ss.str());

    delete robot;
}

TEST_CASE("Robot3") {
    Machine * robot = new Robot("goldorak");
    int etat = 0;

    try {
        robot->bouge();
    } catch (ImpossibleException& e) {
        etat = 3;
    } catch (std::exception& e) {
        etat = 2;
    } catch (...) {
        etat = 1;
    }

    delete robot;
    
    REQUIRE(etat >= 2);
    REQUIRE(3 == etat);
}

TEST_CASE("soucoupe1") {
    Pilote pilote("phenicia");
    Machine * soucoupe = new Soucoupe("fossoirak");
    soucoupe->setPilote(&pilote);
    std::stringstream ss;
    
    ss << soucoupe->bouge();

    REQUIRE("phenicia pilote fossoirak qui vole" == ss.str());

    delete soucoupe;
}


TEST_CASE("soucoupe2") {
    Machine * soucoupe = new Soucoupe("spazer");
    soucoupe->setAutomatique(true);
    std::stringstream ss;
    
    ss << soucoupe->bouge();
    
    REQUIRE("spazer vole en mode automatique" == ss.str());

    delete soucoupe;
}


TEST_CASE("arme1") {
    Arme arme("canon", 10);
    
    CHECK("canon" == arme.getNom());
    CHECK(10 == arme.getPuissance());

    arme.setPuissance(100);
    CHECK(100 == arme.getPuissance());

    arme.setPuissance(-10);
    CHECK(0 == arme.getPuissance());
}


TEST_CASE("arme2") {
    Machine * robot = new Robot("goldorak");
    std::stringstream ss;
  
    CHECK(0 == robot->getPuissance());

    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("fulguropoint", 200));

    CHECK(300 == robot->getPuissance());

    delete robot;
}

TEST_CASE("arme3") {
    Machine * robot = new Robot("goldorak");
    std::stringstream ss;
  
    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("fulguropoint", 100));

    CHECK(200 == robot->getPuissance());

    robot->getArme("fulguropoint").setPuissance(200);
    CHECK(300 == robot->getPuissance());

    delete robot;
}

TEST_CASE("arme4") {
    Machine * robot = new Robot("goldorak");
    int etat = 0;

    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("fulguropoint", 200));

    try {
        robot->getArme("canon").setPuissance(200);
    } catch (ImpossibleException& e) {
        etat = 3;
    } catch (std::exception& e) {
        etat = 2;
    } catch (...) {
        etat = 1;
    }
    
    REQUIRE(etat >= 2);
    REQUIRE(3 == etat);

    delete robot;
} 

TEST_CASE("arme5") {
    Machine * robot = new Robot("goldorak");
    std::stringstream ss;
  
    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("fulguropoint", 200));

    ss << robot->attaque("cornofulgur");

    CHECK("goldorak attaque avec cornofulgur" == ss.str());

    delete robot;
}


TEST_CASE("arme6") {
    Machine * robot = new Robot("goldorak");
    std::stringstream ss;
    int etat = 0;

    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("fulguropoint", 200));

    try {
        ss << robot->attaque("canon");
    } catch (ImpossibleException& e) {
        etat = 3;
    } catch (std::exception& e) {
        etat = 2;
    } catch (...) {
        etat = 1;
    }
    
    REQUIRE(etat >= 2);
    REQUIRE(3 == etat);

    delete robot;
} 


TEST_CASE("Machine2") {
    int compteur = Machine::getCompteur();
    Robot r("goldorak");
    CHECK( (compteur+1) == Machine::getCompteur());
    Soucoupe s("spazer");
    CHECK( (compteur+2) == Machine::getCompteur());
} 

TEST_CASE("Machine3") {
    int compteur = Machine::getCompteur();
    Golgoth g("golgoth1");
    CHECK( (compteur+1) == Machine::getCompteur());
}

TEST_CASE("Golgoth1") {
    std::stringstream ss1, ss2;

    Golgoth g("golgoth1");

    ss1 << g.bouge();
    REQUIRE("golgoth1 vole en mode automatique" == ss1.str());

    g.setRobot(true);

    ss2 << g.bouge();
    REQUIRE("golgoth1 marche en mode automatique" == ss2.str());

}


TEST_CASE("Machine4") {
    Machine * robot = new Robot("goldorak");
    std::stringstream ss;
  
    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("asterohache", 300));
    robot->ajoute(Arme("fulguropoint", 200));

    ss << robot->checkListeArmesNom();

    CHECK("asterohache\ncornofulgur\nfulguropoint" == ss.str());

    delete robot;
}

TEST_CASE("Machine5") {
    Machine * robot = new Robot("goldorak");
    std::stringstream ss;
  
    robot->ajoute(Arme("cornofulgur", 100));
    robot->ajoute(Arme("asterohache", 300));
    robot->ajoute(Arme("fulguropoint", 200));

    ss << robot->checkListeArmesPuissance();
    CHECK("asterohache\nfulguropoint\ncornofulgur" == ss.str());

    delete robot;
}

*/
