#include <gtest/gtest.h>
#include <json.hpp>
#include <httplib.h>
//#define private public
#include "OptimizerEvolutionary.h"
#include <ProcessorStandard.h>
#include <ModuleSQL.h>
#include <ModuleSwitch.h>
#include <math.h>
#include <thread>
/*
using namespace mdd;
TEST(ModuleHTTP, test_ansys_sql_server) {
    std::shared_ptr<ModuleSQL> sql = std::make_shared<ModuleSQL>("../../../lib/test/db/materials.db");
    std::shared_ptr<ModuleHTTP> http = std::make_shared<ModuleHTTP>("", "localhost", 8888);//../../../lib/test/server/server-ansys.py

    auto sql_inputs = sql->getInputIDs();
    auto sql_outputs = sql->getOutputIDs();
    auto http_inputs = http->getInputIDs();
    auto http_outputs = http->getOutputIDs();
    sql->getInput(sql_inputs[0])->setValue() = { 1 };

    //test http
    std::cout << "http-TEST" << std::endl;
    for (size_t i = 0; i < http_inputs.size(); i++)
    {
        std::cout << http->getInput(http_inputs[i])->getValue()[0] << std::endl;
    }
    for (size_t i = 2; i < sql_outputs.size(); i++)//0: ID 1: Name
    {
        http->getInput(http_inputs[i - 2])->connect(sql->getOutput(sql_outputs[i]));
    }
    http->getInput(http_inputs.back())->setOptimizability(true);
    limits limit;
    limit.min = { 0, 0, 0, 0, 0, 0 };
    limit.max = { 90, 90, 90, 90, 90, 90 };
    limit.rule = "val[0] != val[5] || val[1] != val[4] || val[2] != val[3]";
    http->getInput(http_inputs.back())->setLimits() = limit;
    //http->getInput(http_inputs.back())->setValue().clear();
    http->getInput(http_inputs.back())->setValue() = { 90,90,0,90,0,90 };

    http->getOutput(http_outputs[3])->setOptimizability(true);

    sql->update();
    //test SQL
    std::cout << "SQL-TEST" << std::endl;
    for (size_t i = 2; i < sql_outputs.size(); i++)
    {
        std::cout<< sql->getOutput(sql_outputs[i])->getValue()[0] <<std::endl;
    }

    http->update();
    EXPECT_FLOAT_EQ(http->getOutput(http_outputs[3])->getValue()[0], 0.31204228291286723);
}

TEST(ModuleHTTP, test_configurations) {
    std::shared_ptr<ModuleSQL> sql = std::make_shared<ModuleSQL>("../../../lib/test/db/materials.db");
    std::shared_ptr<ModuleHTTP> http = std::make_shared<ModuleHTTP>("", "localhost", 8888);//../../../lib/test/server/server-ansys.py

    auto sql_inputs = sql->getInputIDs();
    auto sql_outputs = sql->getOutputIDs();
    auto http_inputs = http->getInputIDs();
    auto http_outputs = http->getOutputIDs();
    sql->getInput(sql_inputs[0])->setValue() = { 1 };
    for (size_t i = 2; i < sql_outputs.size(); i++)//0: ID 1: Name
    {
        http->getInput(http_inputs[i - 2])->connect(sql->getOutput(sql_outputs[i]));
    }
    http->getInput(http_inputs.back())->setOptimizability(true);
    limits limit;
    limit.min = { 0, 0, 0, 0, 0, 0 };
    limit.max = { 90, 90, 90, 90, 90, 90 };
    limit.rule = "val[0] != val[5] or val[1] != val[4] or val[2] != val[3]";
    http->getInput(http_inputs.back())->setLimits() = limit;

    http->getOutput(http_outputs[3])->setOptimizability(true);

    std::shared_ptr<ProcessorStandard> processor = std::make_shared<ProcessorStandard>();;
    processor->addModule(sql);
    processor->addModule(http);
    auto mods = processor->getModuleIDs();

    OptimizerEvolutionary optimizer(processor, 3, 20, 0.13, 5);
    optimizer.setEvaluation("out0");

    //auto res = optimizer.update();
    OptimizerEvolutionary::Individual ind;
    ind.dna = { { 0,90,90,90,90,90 } };
    std::cout << "{ 0,90,90,90,90,90 }: " << optimizer.evaluateFitness(ind) << std::endl;
    ind.dna = { { 90,90,90,90,90,0 } };
    std::cout << "{ 90,90,90,90,90,0 }: " << optimizer.evaluateFitness(ind) << std::endl;
    ind.dna = { { 90,0,0,0,0,0 } };
    std::cout << "{ 90,0,0,0,0,0 }: " << optimizer.evaluateFitness(ind) << std::endl;
    ind.dna = { { 0,0,0,0,0,90 } };
    std::cout << "{ 0,0,0,0,0,90 }: " << optimizer.evaluateFitness(ind) << std::endl;
    ind.dna = { { 0,0,0,0,0,0 } };
    std::cout << "{ 0,0,0,0,0,0 }: " << optimizer.evaluateFitness(ind) << std::endl;
    ind.dna = { { 90,90,90,90,90,90 } };
    std::cout << "{ 90,90,90,90,90,90 }: " << optimizer.evaluateFitness(ind) << std::endl;
    ind.dna = { { 0,0,90,90,90,90 } };
    std::cout << "{ 0,0,90,90,90,90 }: " << optimizer.evaluateFitness(ind) << std::endl;
    EXPECT_TRUE(ind.fitness <= 100.0);
}

TEST(ModuleHTTP, test_ansys_server) {
    std::shared_ptr<ModuleSQL> sql = std::make_shared<ModuleSQL>("../../../lib/test/db/materials.db");
    std::shared_ptr<ModuleHTTP> http = std::make_shared<ModuleHTTP>("", "localhost", 8888);//../../../lib/test/server/server-ansys.py

    auto sql_inputs = sql->getInputIDs();
    auto sql_outputs = sql->getOutputIDs();
    auto http_inputs = http->getInputIDs();
    auto http_outputs = http->getOutputIDs();
    sql->getInput(sql_inputs[0])->setValue() = { 1 };
    for (size_t i = 2; i < sql_outputs.size(); i++)//0: ID 1: Name
    {
        http->getInput(http_inputs[i - 2])->connect(sql->getOutput(sql_outputs[i]));
    }
    http->getInput(http_inputs.back())->setOptimizability(true);
    limits limit;
    limit.min = { 0, 0, 0, 0, 0, 0 };
    limit.max = { 90, 90, 90, 90, 90, 90 };
    limit.rule = "val[0] != val[5] or val[1] != val[4] or val[2] != val[3]";
    http->getInput(http_inputs.back())->setLimits() = limit;

    http->getOutput(http_outputs[3])->setOptimizability(true);
   
    std::shared_ptr<ProcessorStandard> processor = std::make_shared<ProcessorStandard>();;
    processor->addModule(sql);
    processor->addModule(http);
    auto mods = processor->getModuleIDs();

    OptimizerEvolutionary optimizer(processor, 3, 20, 0.13, 5);
    optimizer.setEvaluation("out0");

    auto res = optimizer.update();
    std::cout << optimizer.getBest().fitness << std::endl;
    std::cout << optimizer.evaluateFitness(optimizer.getBest()) << std::endl;
    EXPECT_TRUE(optimizer.getBest().fitness <= 100.0);
}
//*/