package fakestorage // import "github.com/docker/docker/internal/test/fakestorage"

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"strings"

	"github.com/docker/docker/api/types"
	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
	"github.com/docker/docker/internal/test"
	"github.com/docker/docker/internal/test/environment"
	"github.com/docker/docker/internal/test/fakecontext"
	"github.com/docker/docker/internal/test/request"
	"github.com/docker/docker/internal/testutil"
	"github.com/docker/go-connections/nat"
	"gotest.tools/assert"
)

var testEnv *environment.Execution

type testingT interface {
	assert.TestingT
	logT
	skipT
	Fatal(args ...interface{})
	Fatalf(string, ...interface{})
}

type logT interface {
	Logf(string, ...interface{})
}

type skipT interface {
	Skip(reason string)
}

// Fake is a static file server. It might be running locally or remotely
// on test host.
type Fake interface {
	Close() error
	URL() string
	CtxDir() string
}

// SetTestEnvironment sets a static test environment
// TODO: decouple this package from environment
func SetTestEnvironment(env *environment.Execution) {
	testEnv = env
}

// New returns a static file server that will be use as build context.
func New(t testingT, dir string, modifiers ...func(*fakecontext.Fake) error) Fake {
	if ht, ok := t.(test.HelperT); ok {
		ht.Helper()
	}
	if testEnv == nil {
		t.Fatal("fakstorage package requires SetTestEnvironment() to be called before use.")
	}
	ctx := fakecontext.New(t, dir, modifiers...)
	switch {
	case testEnv.IsRemoteDaemon() && strings.HasPrefix(request.DaemonHost(), "unix:///"):
		t.Skip("e2e run : daemon is remote but docker host points to a unix socket")
	case testEnv.IsLocalDaemon():
		return newLocalFakeStorage(ctx)
	default:
		return newRemoteFileServer(t, ctx, testEnv.APIClient())
	}
	return nil
}

// localFileStorage is a file storage on the running machine
type localFileStorage struct {
	*fakecontext.Fake
	*httptest.Server
}

func (s *localFileStorage) URL() string {
	return s.Server.URL
}

func (s *localFileStorage) CtxDir() string {
	return s.Fake.Dir
}

func (s *localFileStorage) Close() error {
	defer s.Server.Close()
	return s.Fake.Close()
}

func newLocalFakeStorage(ctx *fakecontext.Fake) *localFileStorage {
	handler := http.FileServer(http.Dir(ctx.Dir))
	server := httptest.NewServer(handler)
	return &localFileStorage{
		Fake:   ctx,
		Server: server,
	}
}

// remoteFileServer is a containerized static file server started on the remote
// testing machine to be used in URL-accepting docker build functionality.
type remoteFileServer struct {
	host      string // hostname/port web server is listening to on docker host e.g. 0.0.0.0:43712
	container string
	image     string
	client    client.APIClient
	ctx       *fakecontext.Fake
}

func (f *remoteFileServer) URL() string {
	u := url.URL{
		Scheme: "http",
		Host:   f.host}
	return u.String()
}

func (f *remoteFileServer) CtxDir() string {
	return f.ctx.Dir
}

func (f *remoteFileServer) Close() error {
	defer func() {
		if f.ctx != nil {
			f.ctx.Close()
		}
		if f.image != "" {
			if _, err := f.client.ImageRemove(context.Background(), f.image, types.ImageRemoveOptions{
				Force: true,
			}); err != nil {
				fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err)
			}
		}
		if err := f.client.Close(); err != nil {
			fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err)
		}
	}()
	if f.container == "" {
		return nil
	}
	return f.client.ContainerRemove(context.Background(), f.container, types.ContainerRemoveOptions{
		Force:         true,
		RemoveVolumes: true,
	})
}

func newRemoteFileServer(t testingT, ctx *fakecontext.Fake, c client.APIClient) *remoteFileServer {
	var (
		image     = fmt.Sprintf("fileserver-img-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10)))
		container = fmt.Sprintf("fileserver-cnt-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10)))
	)

	ensureHTTPServerImage(t)

	// Build the image
	if err := ctx.Add("Dockerfile", `FROM httpserver
COPY . /static`); err != nil {
		t.Fatal(err)
	}
	resp, err := c.ImageBuild(context.Background(), ctx.AsTarReader(t), types.ImageBuildOptions{
		NoCache: true,
		Tags:    []string{image},
	})
	assert.NilError(t, err)
	_, err = io.Copy(ioutil.Discard, resp.Body)
	assert.NilError(t, err)

	// Start the container
	b, err := c.ContainerCreate(context.Background(), &containertypes.Config{
		Image: image,
	}, &containertypes.HostConfig{}, nil, container)
	assert.NilError(t, err)
	err = c.ContainerStart(context.Background(), b.ID, types.ContainerStartOptions{})
	assert.NilError(t, err)

	// Find out the system assigned port
	i, err := c.ContainerInspect(context.Background(), b.ID)
	assert.NilError(t, err)
	newP, err := nat.NewPort("tcp", "80")
	assert.NilError(t, err)
	ports, exists := i.NetworkSettings.Ports[newP]
	if !exists || len(ports) != 1 {
		t.Fatalf("unable to find port 80/tcp for %s", container)
	}
	host := ports[0].HostIP
	port := ports[0].HostPort

	return &remoteFileServer{
		container: container,
		image:     image,
		host:      fmt.Sprintf("%s:%s", host, port),
		ctx:       ctx,
		client:    c,
	}
}
