package resource

import (
	"encoding/json"
	"io"
	"net/url"
	"reflect"

	apiresource "github.com/pingcap/test-infra/common/model/resource"

	"github.com/pingcap/test-infra/sdk/core"
)

// Client defines apis every resource need to impl
type Client interface {
	// Create creates resource
	Create(spec json.RawMessage) (core.Resource, error)
	// Get gets resource
	Get(handle apiresource.ResourceHandle) (core.Resource, error)
	// GetEndpoints gets Endpoints of a resource
	GetEndpoints(handle apiresource.ResourceHandle) (apiresource.ResourceEndpoints, error)
	// Delete deletes resources
	Delete(handle apiresource.ResourceHandle) error
	// ReserveEnv reserves environment without the loss of debugging on resource
	ReserveEnv(handle apiresource.ResourceHandle, action apiresource.GcReserveEnvAction) error
	// Artifact archives logs for debugging on resource
	Artifact(handle apiresource.ResourceHandle, action apiresource.GcArtifactAction, archiver ArchiverFunc) (map[string]*url.URL, error)
	// FQDN return the fully qualified domain name of the Client
	FQDN() string
}

// ArchiverFunc is a type alias, extract it for easy when refactor
type ArchiverFunc func(objectName string, reader io.Reader) (*url.URL, error)

type RemoteCommander interface {
	Wait() RemoteCommandErr
}

type RemoteCommanderInterruptible interface {
	RemoteCommander
	Interrupt() error
}

type RemoteCommandErr struct {
	Err      error
	ExitCode int
}

func FQDN(x interface{}) string {
	t := reflect.TypeOf(x)
	return t.PkgPath() + "." + t.Name()
}
