package client

import (
	"context"
	"errors"
	"fmt"
	"net/http"

	cerrdefs "github.com/containerd/errdefs"
	"github.com/containerd/errdefs/pkg/errhttp"
	"github.com/moby/moby/client/pkg/versions"
)

// errConnectionFailed implements an error returned when connection failed.
type errConnectionFailed struct {
	error
}

// Error returns a string representation of an errConnectionFailed
func (e errConnectionFailed) Error() string {
	return e.error.Error()
}

func (e errConnectionFailed) Unwrap() error {
	return e.error
}

// IsErrConnectionFailed returns true if the error is caused by connection failed.
func IsErrConnectionFailed(err error) bool {
	return errors.As(err, &errConnectionFailed{})
}

// connectionFailed returns an error with host in the error message when connection
// to docker daemon failed.
func connectionFailed(host string) error {
	var err error
	if host == "" {
		err = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
	} else {
		err = fmt.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host)
	}
	return errConnectionFailed{error: err}
}

type objectNotFoundError struct {
	object string
	id     string
}

func (e objectNotFoundError) NotFound() {}

func (e objectNotFoundError) Error() string {
	return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
}

// requiresVersion returns an error if the APIVersion required is less than the
// current supported version.
//
// It performs API-version negotiation if the Client is configured with this
// option, otherwise it assumes the latest API version is used.
func (cli *Client) requiresVersion(ctx context.Context, apiRequired, feature string) error {
	// Make sure we negotiated (if the client is configured to do so),
	// as code below contains API-version specific handling of options.
	//
	// Normally, version-negotiation (if enabled) would not happen until
	// the API request is made.
	if err := cli.checkVersion(ctx); err != nil {
		return err
	}
	if cli.version != "" && versions.LessThan(cli.version, apiRequired) {
		return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, apiRequired, cli.version)
	}
	return nil
}

type httpError struct {
	err    error
	errdef error
}

func (e *httpError) Error() string {
	return e.err.Error()
}

func (e *httpError) Unwrap() error {
	return e.err
}

func (e *httpError) Is(target error) bool {
	return errors.Is(e.errdef, target)
}

// httpErrorFromStatusCode creates an errdef error, based on the provided HTTP status-code
func httpErrorFromStatusCode(err error, statusCode int) error {
	if err == nil {
		return nil
	}
	base := errhttp.ToNative(statusCode)
	if base != nil {
		return &httpError{err: err, errdef: base}
	}

	switch {
	case statusCode >= http.StatusOK && statusCode < http.StatusBadRequest:
		// it's a client error
		return err
	case statusCode >= http.StatusBadRequest && statusCode < http.StatusInternalServerError:
		return &httpError{err: err, errdef: cerrdefs.ErrInvalidArgument}
	case statusCode >= http.StatusInternalServerError && statusCode < 600:
		return &httpError{err: err, errdef: cerrdefs.ErrInternal}
	default:
		return &httpError{err: err, errdef: cerrdefs.ErrUnknown}
	}
}
