#include <curlpp/Easy.hpp>
#include <curlpp/cURLpp.hpp>
#include <exception>
#include <kubecontrol/KubernetesAPI.hpp>
#include <list>
#include <curlpp/Options.hpp>
#include <sstream>

#include <loguru.hpp>




namespace kubecontrol {

    KubernetesAPI::KubernetesAPI()
    {

    }


    KubernetesAPI::KubernetesAPI(YAML::Node config)
    {
        addYaml(config);
    }


    KubernetesAPI::KubernetesAPI(std::string APIAddress, std::string Token)
    :APIAddress_(APIAddress), Token_(Token)
    {

    }


    void  KubernetesAPI::addAddress(std::string address)
    {
        APIAddress_ = address;
    }

    std::string KubernetesAPI::getAddress()
    {
        return APIAddress_;
    }

    void  KubernetesAPI::addToken(std::string token)
    {
        Token_ = token;
    }


    std::string KubernetesAPI::getNamespace()
    {
        return Namespace_;
    }

    void  KubernetesAPI::addYaml(YAML::Node config)
    {
        try {
        
        Token_ = config["users"][0]["user"]["token"].as<std::string>();
        Namespace_ = config["contexts"][0]["context"]["namespace"].as<std::string>();

        char * KUBERNETES_SERVICE_HOST = std::getenv("KUBERNETES_SERVICE_HOST");
        char * KUBERNETES_SERVICE_PORT = std::getenv("KUBERNETES_SERVICE_PORT");

        if (KUBERNETES_SERVICE_HOST != nullptr && KUBERNETES_SERVICE_PORT!= nullptr) 
        {
            APIAddress_ = "https://" +std::string(KUBERNETES_SERVICE_HOST)+":"+std::string(KUBERNETES_SERVICE_PORT);
        } else
        {
            LOG_S(INFO)<<"Taking Serveraddress out of the provided YAML file";

            APIAddress_ = config["clusters"][0]["cluster"]["server"].as<std::string>();
        }   

        } catch (std::exception& e) {
            LOG_S(ERROR)<< e.what();
            throw e.what();
        } 
    }

    std::string  KubernetesAPI::performRequest(std::string request,std::string Methode )
    {
        std::stringstream result;
        
        std::string curlURL = APIAddress_+request;
        std::string AuthString = "Authorization: Bearer " + Token_;

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


        curlpp::Cleanup cleaner;
        curlpp::Easy curlRequest;

        curlRequest.setOpt(cURLpp::Options::WriteStream(&result));

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

        curlRequest.setOpt(new curlpp::options::Url(curlURL));
     
        curlRequest.setOpt(new curlpp::options::SslVerifyPeer(false));
        curlRequest.setOpt(new curlpp::options::CustomRequest(Methode));


        try {
            curlRequest.perform();

        } catch (const std::exception e) {
            LOG_S(ERROR)<<e.what();
        }
        curlRequest.reset();
        return result.str();
    }

    std::string  KubernetesAPI::performRequest(std::string request,std::string Methode,std::string PostFields)
    {



        std::string curlURL = APIAddress_+request;;
        std::string AuthString = "Authorization: Bearer " + Token_;

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


        curlpp::Cleanup cleaner;
        curlpp::Easy curlRequest;

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

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

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

        curlRequest.setOpt(new curlpp::options::SslVerifyPeer(false));

        curlRequest.setOpt(new curlpp::options::CustomRequest("POST"));

        curlRequest.setOpt(new curlpp::options::PostFields(PostFields));


        curlRequest.perform();
        
        curlRequest.reset();
   
        
        return  result.str();

    }
}