package db

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/tidbcloud/metrics-server/pkg/docker_db/db/iface"
	"github.com/tidbcloud/metrics-server/pkg/docker_db/db/impl"
)

var (
	Manager    iface.IManager = &ExternalProcessManager{}
	ServerPort                = uint16(11234)
)

func BorrowDB() (*iface.DockerDB, error) {
	return Manager.BorrowDB()
}

func ReleaseDB(id string) {
	Manager.ReleaseDB(id)
}

type InProcessManager struct{}

func (i *InProcessManager) ReleaseAll() {
	impl.ReleaseAll()
}

func (i *InProcessManager) BorrowDB() (*iface.DockerDB, error) {
	return impl.BorrowDB()
}

func (i *InProcessManager) ReleaseDB(id string) {
	impl.ReleaseDB(id)
}

type ExternalProcessManager struct{}

func (i *ExternalProcessManager) ReleaseAll() {
	resp, _ := http.Get(fmt.Sprintf("http://127.0.0.1:%d/releaseAll", ServerPort))
	if resp != nil {
		_ = resp.Body.Close()
	}
}

func (i *ExternalProcessManager) BorrowDB() (*iface.DockerDB, error) {
	res, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/borrow", ServerPort))
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, fmt.Errorf("failed to call server")
	}
	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	err = res.Body.Close()
	if err != nil {
		return nil, err
	}

	var d iface.DockerDB
	fmt.Printf("%v", d)
	_ = json.Unmarshal(data, &d)
	return &d, nil
}

func (i *ExternalProcessManager) ReleaseDB(id string) {
	resp, _ := http.Get(fmt.Sprintf("http://127.0.0.1:%d/release?id=%s", ServerPort, id))
	if resp != nil {
		_ = resp.Body.Close()
	}
}
