#pragma once

#include <kubecontrol/KubernetesAPI.hpp>
#include "nlohmann/json_fwd.hpp"
#include "yaml-cpp/node/node.h"
#include <map>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include <yaml-cpp/yaml.h>
#include <fstream>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <loguru.hpp>
#include <nlohmann/json.hpp>

#include <curlpp/cURLpp.hpp>
#include <filesystem>
#include <kubecontrol/Container.hpp>


namespace kubecontrol
{


    struct PodChild
    {
        std::string UUID;
        std::string IP;
        std::string Component;
        std::string Status;

    };
    struct PodInfos
    {
        std::string UUID;
        std::string IP;
        std::string Status;
        std::string Component;
        std::string Owner;
        std::vector<PodChild> Childs;
    };




    class KubePod
    {
        public:
            KubePod(const std::string &Owner, const std::string &Uuid, const std::string &ContainerImage, const std::string &Namespace = "simulator") ;
            KubePod(const std::string &Owner, const std::string &Uuid, const  std::string &Component,  const std::string &ContainerImage, const std::string &Namespace = "simulator");

            /**
             * @brief returns the uuid of the pod
             *
             * @return std::string
             */
            std::string getUUID();

            /**
             * @brief Get the Owner of the pods
             *
             * @return std::string
             */
            std::string getOwner();

            /**
             * @brief Get the Ip of the pod
             *
             * @return std::string
             */
            std::string getIp();

            /**
             * @brief Get the Status
             *
             * @return std::string
             */
            std::string getStatus();

            /**
             * @brief Set the Environment Vars for pod
             *
             * @param key
             * @param val
             */
            void setEnvironmentVar(std::string key, std::string val);

            /**
             * @brief Get the Environment Vars
             *
             * @return std::map<std::string, std::string>
             */
            std::map<std::string, std::string> GetEnvironmentVars();

            /**
             * @brief Get the Environment Var for a specific key
             *
             * @param key std::string
             * @return std::string
             */
            std::string GetEnvironmentVar(std::string key);

            /**
             * @brief Set CMD args
             *
             * @param args
             */
            void setArgs(std::string &args);

            /**
             * @brief Get the Args
             *
             * @return std::vector<std::string>
             */
            std::vector<std::string> GetArgs();

            /**
             * @brief Set the Command for a pod
             *
             * @param command
             */
            void setCommand(std::string &command);

            /**
             * @brief Get the Command
             *
             * @return std::string
             */
            std::string getCommand();

            /**
             * @brief Set the Component var for the pod
             *
             * @param component
             */
            void setComponent(std::string &component);

            /**
             * @brief Get the Component var
             *
             * @return std::string
             */
            std::string getComponent();

            /**
             * @brief add a Container to a pod
             *
             * @param name std::string
             * @param image std::string
             * @param envs std::map<std::string,std:.string>
             * @param PullPolicy std::string (defualt: Always) possible:( IfNotPresent, Never)
             */
            void addContainer(std::string name,std::string image, std::map<std::string, std::string> &envs , kubecontrol::PullPolicy pullPolicy = ALWAYS);

            /**
             * @brief add container object
             *
             * @param containter
             */
            void addContainer(Container containter);

            /**
             * @brief
             *
             * @param containerUUID
             * @param envs
             */
            void addEnvValuesToContainer(std::string containerUUID, std::map<std::string, std::string> envs);

            /**
            * @brief sets the name of the pod
            * @param string - term to be displayed
            */
            void setName(std::string &name);

            /**
            * @brief return the name of the pod
            * @return std::string
            */
            std::string getName();


            int start(KubernetesAPI APIInterface,bool WaitTillRunning = true);
            int stop(KubernetesAPI APIInterface);
            int stopChilds(KubernetesAPI APIInterface);


            /**
            *@brief updates the infos for a pod from the give Kubernetes API
            *@param KubernetesAPI - object of KubernetesAPI wich holds all necessary to perfom requests
            *@return returns 1 on failure
            */
            int updateInfoForThisPod(KubernetesAPI APIInterface);

            std::vector<PodChild> getPodsChilds(KubernetesAPI APIInterface);


        private:

            static const int MaxWaitTimeInSeconds;


            std::string Owner_;
            std::string Uuid_;
            std::string Name_;
            std::string Component_;
            std::vector<Container> ContainerImages_;
            // std::string ContainerImage_;
            std::string ContainerRegistry_;
            std::string PathToYaml_;
            std::string Namespace_;

            std::string Ip_;
            std::string Status_;
            std::string PartOf_;
            std::vector<PodChild> ChildPods;

            std::string PodCommand_;

            YAML::Node YAMLNode_;

            std::map<std::string, std::string> EnvirmonentVars_;
            std::vector<std::string> Args_;

            std::string createYAML();

            /**
             * @brief extracts the asked inforamtion from the kubernetes response
             *
             *
            */
            int extractInformationFromResopnse(std::string response);



    };
}
