#include <gtest/gtest.h>
#include <json.hpp>
#include <httplib.h>
//#define private public
#include <Registration.h>
#include <math.h>
#include <thread>

using namespace mdd;
using namespace httplib;

namespace TEST_MODULE_HTTP{
    /*
void serverThread()
{
    Server svr;
    json input;
    json output;
    std::string status = "ready";

    for (int i = 0; i < 5; ++i) {
        json entity;
        entity["type"] = "INPUT";
        entity["value"] = { i };
        input.push_back(entity);
    }

    for (int i = 0; i < 3; ++i) {
        json entity;
        entity["type"] = "OUTPUT";
        entity["value"] = { i * 2 };
        output.push_back(entity);
    }

    svr.Get("/inputs", [&](const Request& req, Response& res) {
        res.set_content(input.dump(), "application/json");
    });

    svr.Get("/outputs", [&](const Request& req, Response& res) {
        res.set_content(output.dump(), "application/json");
    });

    svr.Get("/status", [&](const Request& req, Response& res) {
        try{
            json body;
            body["status"] = status;
            std::cout << status << std::endl;
            res.set_content(body.dump(), "application/json");
        }
        catch(std::exception){
            std::cout << "Exeption caught"<<std::endl;
        }
    });

    svr.Post("/update",
            [&](const Request& req, Response& res, const ContentReader &content_reader) {
                status = "updating...";
                std::string body;
                content_reader([&](const char *data, size_t data_length) {
                    body.append(data, data_length);
                    return true;
                });
                body = std::string(R"()") + body;
                json inputs = json::parse(body.c_str());
                for (int i = 0; i < inputs.size(); ++i) {
                    input[i]["value"] = inputs[i]["value"];
                }
                output[0]["value"][0] = input[0]["value"][0].get<int>() + input[1]["value"][0].get<int>();
                output[1]["value"][0] = input[2]["value"][0].get<int>() * input[2]["value"][0].get<int>();
                output[2]["value"][0] = input[3]["value"][0].get<int>() - input[4]["value"][0].get<int>();
                //std::cout << output[0].dump() << std::endl;
                //std::cout << output[1].dump() << std::endl;
                //std::cout << output[2].dump() << std::endl;
                res.set_content(output.dump(), "application/json");
                status = "ready";
             }
    );

    svr.Get("/stop", [&](const Request& req, Response& res) {
        std::cout << "server stoped"<<std::endl;
        svr.stop();
    });
    svr.listen("localhost", 8888);
    std::cout << "server closed"<<std::endl;
}

auto regi = Registration();

TEST(ModuleHTTP, updateLayout_intern){
    std::thread server (serverThread);
    auto mod = regi.generateModule("ModuleHTTP");// ("", "localhost", 8888);
    json config = mod->getConfiguration();
    config["path"]["value"] = "";
    config["url"]["value"] = "localhost";
    config["port"]["value"] = 8888;
    mod->configure(config.dump());

    Client cli("localhost",8888);
    cli.Get("/stop");
    server.join();

    for (int i = 0; i < mod->getNumInputs(); ++i) {
        EXPECT_EQ(mod->getInput(i)->getType(), "INPUT");
        EXPECT_EQ((int)mod->getInput(i)->getValue()[0], i);
    }

    for (int i = 0; i < mod->getNumOutputs(); ++i) {
        EXPECT_EQ(mod->getOutput(i)->getType(), "OUTPUT");
        EXPECT_EQ((int)mod->getOutput(i)->getValue()[0], i * 2);
    }
    mod->disconnect();
}


TEST(ModuleHTTP, updateLayout_extern){
    auto mod = regi.generateModule("ModuleHTTP");// ("", "localhost", 8888);
    json config = mod->getConfiguration();
    config["path"]["value"] = "../../../lib/test/server/server.py";
    config["url"]["value"] = "localhost";
    config["port"]["value"] = 8889;
    mod->configure(config);
   
    for (int i = 0; i < mod->getNumInputs(); ++i) {
        EXPECT_EQ(mod->getInput(i)->getType(), "INPUT");
        EXPECT_EQ((int)mod->getInput(i)->getValue()[0], i);
    }

    for (int i = 0; i < mod->getNumOutputs(); ++i) {
        EXPECT_EQ(mod->getOutput(i)->getType(), "OUTPUT");
        EXPECT_EQ((int)mod->getOutput(i)->getValue()[0], i * 2);
    }
    Client cli("localhost",8889);
    cli.Get("/stop");
    mod->disconnect();
}

TEST(ModuleHTTP, update_intern){
    std::thread server (serverThread);
    auto mod = regi.generateModule("ModuleHTTP");// ("", "localhost", 8888);
    json config = mod->getConfiguration();
    config["configure"]["path"]["value"] = "";
    config["configure"]["url"]["value"] = "localhost";
    config["configure"]["port"]["value"] = 8888;
    mod->configure(config);

    for (int i = 0; i < mod->getNumInputs(); ++i) {
        mod->getInput(i)->setValue() = { (double)(10 - i) };
    }
    mod->update();

    Client cli("localhost", 8888);
    cli.Get("/stop");
    server.join();

    for (int i = 0; i < mod->getNumInputs(); ++i) {
        EXPECT_EQ(mod->getInput(i)->getType(), "INPUT");
        EXPECT_EQ(mod->getInput(i)->getValue()[0], 10-i);
    }
    //std::cout << "WORKED" << std::endl;
    //std::cout << module.getOutput(outputs_ids[0])->getValue() << std::endl;
    EXPECT_EQ((int)mod->getOutput(0)->getValue()[0], 19);
    EXPECT_EQ((int)mod->getOutput(1)->getValue()[0], 64);
    EXPECT_EQ((int)mod->getOutput(2)->getValue()[0], 1);
    mod->disconnect();
}
//*/
}