package tools

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
)

// HTTP Method Enum defines the different methods that can be used to interact with the HTTP server
type METHOD int

const (
	GET METHOD = iota
	PUT
	POST
	DELETE
)

// String returns the string of the enum
func (m METHOD) String() string {
	return [...]string{"GET", "PUT", "POST", "DELETE"}[m]
}

// EnumIndex returns the index of the enum
func (m METHOD) EnumIndex() int {
	return int(m)
}

// ToMethod returns the method from a string
func ToMethod(str string) METHOD {
	for _, s := range []METHOD{GET, PUT, POST, DELETE} {
		if s.String() == str {
			return s
		}
	}
	return GET
}

var HTTPCallerInstance = &HTTPCaller{} // Singleton instance of the HTTPCaller

type HTTPCaller struct {
	URLS     map[DataType]map[METHOD]string // Map of the different methods and their urls
	Disabled bool                           // Disabled flag
}

// NewHTTPCaller creates a new instance of the HTTP Caller
func NewHTTPCaller(urls map[DataType]map[METHOD]string) *HTTPCaller {
	return &HTTPCaller{
		URLS:     urls, // Set the urls defined in the config & based on the data name type & method
		Disabled: false,
	}
}

// CallGet calls the GET method on the HTTP server
func (caller *HTTPCaller) CallGet(url string, subpath string) ([]byte, error) {
	resp, err := http.Get(url + subpath)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return io.ReadAll(resp.Body)
}

// CallPut calls the DELETE method on the HTTP server
func (caller *HTTPCaller) CallDelete(url string, subpath string) ([]byte, error) {
	resp, err := http.NewRequest("DELETE", url+subpath, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return io.ReadAll(resp.Body)
}

// CallPost calls the POST method on the HTTP server
func (caller *HTTPCaller) CallPost(url string, subpath string, body map[string]interface{}) ([]byte, error) {
	postBody, _ := json.Marshal(body)
	responseBody := bytes.NewBuffer(postBody)
	resp, err := http.Post(url+subpath, "application/json", responseBody)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return io.ReadAll(resp.Body)
}

// NO PUT IN HERE TO DANGEROUS TO USE ON A REMOTE SERVER, MAYBE NEEDED IN THE FUTURE
