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

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/docker/docker/internal/test"
	"github.com/opencontainers/go-digest"
	"gotest.tools/assert"
)

const (
	// V2binary is the name of the registry v2 binary
	V2binary = "registry-v2"
	// V2binarySchema1 is the name of the registry that serve schema1
	V2binarySchema1 = "registry-v2-schema1"
	// DefaultURL is the default url that will be used by the registry (if not specified otherwise)
	DefaultURL = "127.0.0.1:5000"
)

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

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

// V2 represent a registry version 2
type V2 struct {
	cmd         *exec.Cmd
	registryURL string
	dir         string
	auth        string
	username    string
	password    string
	email       string
}

// Config contains the test registry configuration
type Config struct {
	schema1     bool
	auth        string
	tokenURL    string
	registryURL string
}

// NewV2 creates a v2 registry server
func NewV2(t testingT, ops ...func(*Config)) *V2 {
	if ht, ok := t.(test.HelperT); ok {
		ht.Helper()
	}
	c := &Config{
		registryURL: DefaultURL,
	}
	for _, op := range ops {
		op(c)
	}
	tmp, err := ioutil.TempDir("", "registry-test-")
	assert.NilError(t, err)
	template := `version: 0.1
loglevel: debug
storage:
    filesystem:
        rootdirectory: %s
http:
    addr: %s
%s`
	var (
		authTemplate string
		username     string
		password     string
		email        string
	)
	switch c.auth {
	case "htpasswd":
		htpasswdPath := filepath.Join(tmp, "htpasswd")
		// generated with: htpasswd -Bbn testuser testpassword
		userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m"
		username = "testuser"
		password = "testpassword"
		email = "test@test.org"
		err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644))
		assert.NilError(t, err)
		authTemplate = fmt.Sprintf(`auth:
    htpasswd:
        realm: basic-realm
        path: %s
`, htpasswdPath)
	case "token":
		authTemplate = fmt.Sprintf(`auth:
    token:
        realm: %s
        service: "registry"
        issuer: "auth-registry"
        rootcertbundle: "fixtures/registry/cert.pem"
`, c.tokenURL)
	}

	confPath := filepath.Join(tmp, "config.yaml")
	config, err := os.Create(confPath)
	assert.NilError(t, err)
	defer config.Close()

	if _, err := fmt.Fprintf(config, template, tmp, c.registryURL, authTemplate); err != nil {
		// FIXME(vdemeester) use a defer/clean func
		os.RemoveAll(tmp)
		t.Fatal(err)
	}

	binary := V2binary
	if c.schema1 {
		binary = V2binarySchema1
	}
	cmd := exec.Command(binary, confPath)
	if err := cmd.Start(); err != nil {
		// FIXME(vdemeester) use a defer/clean func
		os.RemoveAll(tmp)
		t.Fatal(err)
	}
	return &V2{
		cmd:         cmd,
		dir:         tmp,
		auth:        c.auth,
		username:    username,
		password:    password,
		email:       email,
		registryURL: c.registryURL,
	}
}

// WaitReady waits for the registry to be ready to serve requests (or fail after a while)
func (r *V2) WaitReady(t testingT) {
	if ht, ok := t.(test.HelperT); ok {
		ht.Helper()
	}
	var err error
	for i := 0; i != 50; i++ {
		if err = r.Ping(); err == nil {
			return
		}
		time.Sleep(100 * time.Millisecond)
	}
	t.Fatalf("timeout waiting for test registry to become available: %v", err)
}

// Ping sends an http request to the current registry, and fail if it doesn't respond correctly
func (r *V2) Ping() error {
	// We always ping through HTTP for our test registry.
	resp, err := http.Get(fmt.Sprintf("http://%s/v2/", r.registryURL))
	if err != nil {
		return err
	}
	resp.Body.Close()

	fail := resp.StatusCode != http.StatusOK
	if r.auth != "" {
		// unauthorized is a _good_ status when pinging v2/ and it needs auth
		fail = fail && resp.StatusCode != http.StatusUnauthorized
	}
	if fail {
		return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
	}
	return nil
}

// Close kills the registry server
func (r *V2) Close() {
	r.cmd.Process.Kill()
	r.cmd.Process.Wait()
	os.RemoveAll(r.dir)
}

func (r *V2) getBlobFilename(blobDigest digest.Digest) string {
	// Split the digest into its algorithm and hex components.
	dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex()

	// The path to the target blob data looks something like:
	//   baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data"
	return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", r.dir, dgstAlg, dgstHex[:2], dgstHex)
}

// ReadBlobContents read the file corresponding to the specified digest
func (r *V2) ReadBlobContents(t assert.TestingT, blobDigest digest.Digest) []byte {
	if ht, ok := t.(test.HelperT); ok {
		ht.Helper()
	}
	// Load the target manifest blob.
	manifestBlob, err := ioutil.ReadFile(r.getBlobFilename(blobDigest))
	assert.NilError(t, err, "unable to read blob")
	return manifestBlob
}

// WriteBlobContents write the file corresponding to the specified digest with the given content
func (r *V2) WriteBlobContents(t assert.TestingT, blobDigest digest.Digest, data []byte) {
	if ht, ok := t.(test.HelperT); ok {
		ht.Helper()
	}
	err := ioutil.WriteFile(r.getBlobFilename(blobDigest), data, os.FileMode(0644))
	assert.NilError(t, err, "unable to write malicious data blob")
}

// TempMoveBlobData moves the existing data file aside, so that we can replace it with a
// malicious blob of data for example.
func (r *V2) TempMoveBlobData(t testingT, blobDigest digest.Digest) (undo func()) {
	if ht, ok := t.(test.HelperT); ok {
		ht.Helper()
	}
	tempFile, err := ioutil.TempFile("", "registry-temp-blob-")
	assert.NilError(t, err, "unable to get temporary blob file")
	tempFile.Close()

	blobFilename := r.getBlobFilename(blobDigest)

	// Move the existing data file aside, so that we can replace it with a
	// another blob of data.
	if err := os.Rename(blobFilename, tempFile.Name()); err != nil {
		// FIXME(vdemeester) use a defer/clean func
		os.Remove(tempFile.Name())
		t.Fatalf("unable to move data blob: %s", err)
	}

	return func() {
		os.Rename(tempFile.Name(), blobFilename)
		os.Remove(tempFile.Name())
	}
}

// Username returns the configured user name of the server
func (r *V2) Username() string {
	return r.username
}

// Password returns the configured password of the server
func (r *V2) Password() string {
	return r.password
}

// Email returns the configured email of the server
func (r *V2) Email() string {
	return r.email
}

// Path returns the path where the registry write data
func (r *V2) Path() string {
	return filepath.Join(r.dir, "docker", "registry", "v2")
}
