package containerd

import (
	"context"
	"io/ioutil"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/docker/docker/libcontainerd"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
	"gotest.tools/assert"
)

func TestLifeCycle(t *testing.T) {
	t.Parallel()

	mock := newMockClient()
	exec, cleanup := setupTest(t, mock, mock)
	defer cleanup()

	id := "test-create"
	mock.simulateStartError(true, id)
	err := exec.Create(id, specs.Spec{}, nil, nil)
	assert.Assert(t, err != nil)
	mock.simulateStartError(false, id)

	err = exec.Create(id, specs.Spec{}, nil, nil)
	assert.NilError(t, err)
	running, _ := exec.IsRunning(id)
	assert.Assert(t, running)

	// create with the same ID
	err = exec.Create(id, specs.Spec{}, nil, nil)
	assert.Assert(t, err != nil)

	mock.HandleExitEvent(id) // simulate a plugin that exits

	err = exec.Create(id, specs.Spec{}, nil, nil)
	assert.NilError(t, err)
}

func setupTest(t *testing.T, client Client, eh ExitHandler) (*Executor, func()) {
	rootDir, err := ioutil.TempDir("", "test-daemon")
	assert.NilError(t, err)
	assert.Assert(t, client != nil)
	assert.Assert(t, eh != nil)

	return &Executor{
			rootDir:     rootDir,
			client:      client,
			exitHandler: eh,
		}, func() {
			assert.Assert(t, os.RemoveAll(rootDir))
		}
}

type mockClient struct {
	mu           sync.Mutex
	containers   map[string]bool
	errorOnStart map[string]bool
}

func newMockClient() *mockClient {
	return &mockClient{
		containers:   make(map[string]bool),
		errorOnStart: make(map[string]bool),
	}
}

func (c *mockClient) Create(ctx context.Context, id string, _ *specs.Spec, _ interface{}) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if _, ok := c.containers[id]; ok {
		return errors.New("exists")
	}

	c.containers[id] = false
	return nil
}

func (c *mockClient) Restore(ctx context.Context, id string, attachStdio libcontainerd.StdioCallback) (alive bool, pid int, err error) {
	return false, 0, nil
}

func (c *mockClient) Status(ctx context.Context, id string) (libcontainerd.Status, error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	running, ok := c.containers[id]
	if !ok {
		return libcontainerd.StatusUnknown, errors.New("not found")
	}
	if running {
		return libcontainerd.StatusRunning, nil
	}
	return libcontainerd.StatusStopped, nil
}

func (c *mockClient) Delete(ctx context.Context, id string) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	delete(c.containers, id)
	return nil
}

func (c *mockClient) DeleteTask(ctx context.Context, id string) (uint32, time.Time, error) {
	return 0, time.Time{}, nil
}

func (c *mockClient) Start(ctx context.Context, id, checkpointDir string, withStdin bool, attachStdio libcontainerd.StdioCallback) (pid int, err error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	if _, ok := c.containers[id]; !ok {
		return 0, errors.New("not found")
	}

	if c.errorOnStart[id] {
		return 0, errors.New("some startup error")
	}
	c.containers[id] = true
	return 1, nil
}

func (c *mockClient) SignalProcess(ctx context.Context, containerID, processID string, signal int) error {
	return nil
}

func (c *mockClient) simulateStartError(sim bool, id string) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if sim {
		c.errorOnStart[id] = sim
		return
	}
	delete(c.errorOnStart, id)
}

func (c *mockClient) HandleExitEvent(id string) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	delete(c.containers, id)
	return nil
}
