#include "nlohmann/json_fwd.hpp"
#include "yaml-cpp/binary.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/node.h"
#include <iomanip>
#include <kubecontrol/kubecontrol.hpp>


#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>

#include <sstream>
#include <string>

#include <yaml-cpp/yaml.h>

#include <loguru.hpp>

#include <nlohmann/json.hpp>


#include <iostream>
#include <fstream>


namespace kubecontrol
{
 
    kubecontrol::kubecontrol(std::string pathToKubectlConfig)
    {
        YAML::Node config = YAML::LoadFile(pathToKubectlConfig);
        
        BearerToken_ = config["users"][0]["user"]["token"].as<std::string>();
        ServerAddress_ = config["clusters"][0]["cluster"]["server"].as<std::string>();

    }

    void kubecontrol::getPods()
    {
    std::string curlURL = ServerAddress_+"/api/v1/namespaces/simulator/pods/";
    std::string AuthString = "Authorization: Bearer " + BearerToken_;

    std::list<std::string> headers;
    headers.push_back(AuthString);


    curlpp::Cleanup cleaner;
    curlpp::Easy request;

   
    std::stringstream result;

    request.setOpt(cURLpp::Options::WriteStream(&result));
    request.setOpt(new curlpp::options::HttpHeader(headers));

    request.setOpt(new curlpp::options::Url(curlURL));
    request.setOpt(new curlpp::options::SslEngineDefault());
    request.setOpt(new curlpp::options::CaPath("config/ca.crt"));
    request.setOpt(new curlpp::options::SslVerifyPeer(false));


    // request.setOpt(new curlpp::options::Verbose(true));


    request.perform();
    auto response = result.str();

  
    
    auto j = nlohmann::json::parse(response);
    LOG_S(INFO)<<j["items"][0]["metadata"];
    //  std::cout << readBuffer << std::endl;

    }

    void kubecontrol::startPod()
    {
    std::string curlURL = ServerAddress_+"/api/v1/namespaces/simulator/pods/";
    std::string AuthString = "Authorization: Bearer " + BearerToken_;

    std::list<std::string> headers;
    headers.push_back(AuthString);
    headers.push_back("Content-Type: application/yaml");


    curlpp::Cleanup cleaner;
    curlpp::Easy request;

    // WriterMemoryClass mWriterChunk;  
    // curlpp::types::WriteFunctionFunctor functor = std::bind(&WriterMemoryClass::WriteMemoryCallback, &mWriterChunk, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    // curlpp::options::WriteFunction *test = new curlpp::options::WriteFunction(functor);
    // request.setOpt(test);
    std::stringstream result;
    request.setOpt(cURLpp::Options::WriteStream(&result));

    request.setOpt(new curlpp::options::HttpHeader(headers));

    request.setOpt(new curlpp::options::Url(curlURL));



    request.setOpt(new curlpp::options::SslEngineDefault());
    request.setOpt(new curlpp::options::CaPath("config/ca.crt"));
    request.setOpt(new curlpp::options::SslVerifyPeer(false));

    request.setOpt(new curlpp::options::Post(true));


    auto yaml = createYAML();

    // YAML::Node node = YAML::LoadFile("config/pods_deployment.yaml");
    // YAML::Binary node = YAML::LoadFile("config/pods_deployment.yaml"); 
    // LOG_S(INFO)<< node["spec"]["containers"][0]["imagePullPolicy"];
    // YAML::Binary binary = node.as<YAML::Binary>();

    std::ifstream is;
    is.open ("config/pods_deployment.yaml", std::ios::binary );

        // get length of file:
    is.seekg (0, std::ios::end);
    long length = is.tellg();
    is.seekg (0, std::ios::beg);

    // allocate memory:
    char *buffer = new char [length];

    // read data as a block:
    is.read (buffer,length);

   
    std::istringstream myStream((std::string( buffer )));
    int size = myStream.str().size();
    is.close();



    request.setOpt(new curlpp::options::PostFields(buffer));

    // request.setOpt(new curlpp::options::Verbose(true));


    request.perform();
    auto response = result.str();
    LOG_S(INFO)<<response;
    }


    void kubecontrol::deletePod(std::string uid)
    {
    std::string curlURL = ServerAddress_+"/api/v1/namespaces/simulator/pods/"+ uid;
    std::string AuthString = "Authorization: Bearer " + BearerToken_;

    std::list<std::string> headers;
    headers.push_back(AuthString);
    // headers.push_back("Content-Type: application/yaml");


    curlpp::Cleanup cleaner;
    curlpp::Easy request;

    std::stringstream result;
    request.setOpt(cURLpp::Options::WriteStream(&result));

    
    request.setOpt(new curlpp::options::HttpHeader(headers));

    request.setOpt(new curlpp::options::Url(curlURL));



    request.setOpt(new curlpp::options::SslEngineDefault());
    request.setOpt(new curlpp::options::CaPath("config/ca.crt"));
    request.setOpt(new curlpp::options::SslVerifyPeer(false));
    
    // request.setOpt(new curlpp::options::Post(true));

    // request.setOpt(new curlpp::options::PostFields("DELETE"));
    request.setOpt(new curlpp::options::CustomRequest("DELETE"));
    // request.setOpt(new curlpp::options::Verbose(true));


    request.perform();
    auto response = result.str();
    // LOG_S(INFO)<<response;

    }


    std::string kubecontrol::createYAML()
    {

     
        YAML::Node node;
        node["apiVersion"] = "v1";
        node["kind"] = "Pod";
        node["metadata"]["name"] = "debug-debian";
        node["metadata"]["labels"]["app.kubernetes.io/name"] = "plaindebian";

        node["spec"]["containers"][0]["name"] = "debug-debian-container";
        node["spec"]["containers"][0]["image"] = "kmaster.ti.unibw-hamburg.de:30808/debugdebianhenry:0.1.3";

      
        // node["spec"]["containers"][0]["imagePullPolicy"] = "\"Always\"";

        node["spec"]["containers"][0]["env"][0]["name"] = "OWN_SHIP_SERVER";
        node["spec"]["containers"][0]["env"][0]["value"] = "127.0.0.1";

        node["spec"]["containers"][0]["env"][1]["name"] = "TOKEN";
        node["spec"]["containers"][0]["env"][1]["value"] = BearerToken_;


        node["spec"]["containers"][0]["args"].SetStyle(YAML::EmitterStyle::Flow);
        node["spec"]["containers"][0]["args"].push_back("-c");
        node["spec"]["containers"][0]["args"].push_back("while true; do echo hello; sleep 5;done");

        node["spec"]["containers"][0]["command"].SetStyle(YAML::EmitterStyle::Flow);
        node["spec"]["containers"][0]["command"].push_back("/bin/sh");

        node["spec"]["restartPolicy"] = "Never";


        std::ofstream fout("config/pods_deployment.yaml");
        std::stringstream ss;
        ss <<node;
        LOG_S(INFO)<< node;
        fout << ss.str();
        fout.close();
        
        return "config/pods_deployment.yaml";

    }
   

}