package context

import (
	"errors"
	"fmt"

	"github.com/docker/cli/cli/command"
	dConfig "github.com/docker/cli/cli/config"
	"github.com/docker/cli/cli/context"
	contextStore "github.com/docker/cli/cli/context/store"
	cliflags "github.com/docker/cli/cli/flags"
	"github.com/moby/term"
)

func NewDefaultDockerContextStore() *command.ContextStoreWithDefault {
	_, _, stderr := term.StdStreams()
	dockerConfig := dConfig.LoadDefaultConfigFile(stderr)
	contextDir := dConfig.ContextStoreDir()
	storeConfig := command.DefaultContextStoreConfig()
	store := newContextStore(contextDir, storeConfig)

	opts := &cliflags.CommonOptions{Context: "default"}

	dockerContextStore := &command.ContextStoreWithDefault{
		Store: store,
		Resolver: func() (*command.DefaultContext, error) {
			return command.ResolveDefaultContext(opts, dockerConfig, storeConfig, stderr)
		},
	}

	return dockerContextStore
}

func GetContextEndpoint(ctx contextStore.Metadata) (string, error) {
	endpointmeta, ok := ctx.Endpoints["docker"].(context.EndpointMetaBase)
	if !ok {
		err := errors.New("context lacks Docker endpoint")
		return "", err
	}
	return endpointmeta.Host, nil
}

func newContextStore(dir string, config contextStore.Config) contextStore.Store {
	return contextStore.New(dir, config)
}

// MissingContextMsg helps end-uers debug missing docker context issues.
var missingContextMsg = `unable to find Docker context for %s?

Please run "abra server ls" to confirm. If you see "unknown" in the table
output then you need to run the following command:

    abra server add %s <args>

See "abra server add --help" for more.
`

// HasDockerContext figures out if a local setup has a working docker context
// configuration or not. This usually tells us if they'll be able to make a SSH
// connection to a server or not and can be a useful way to signal to end-users
// that they need to fix something up if missing.
func HasDockerContext(serverName string) error {
	dockerContextStore := NewDefaultDockerContextStore()
	contexts, err := dockerContextStore.Store.List()
	if err != nil {
		return err
	}

	for _, ctx := range contexts {
		if ctx.Name == serverName {
			return nil
		}
	}

	return fmt.Errorf(missingContextMsg, serverName, serverName)
}