package libcontainerd

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"path/filepath"
	"strconv"
	"strings"

	"syscall"
	"time"

	"github.com/Microsoft/hcsshim"
	"github.com/Sirupsen/logrus"
)

type client struct {
	clientCommon

	// Platform specific properties below here (none presently on Windows)
}

// defaultContainerNAT is the default name of the container NAT device that is
// preconfigured on the server. TODO Windows - Remove for TP5 support as not needed.
const defaultContainerNAT = "ContainerNAT"

// Win32 error codes that are used for various workarounds
// These really should be ALL_CAPS to match golangs syscall library and standard
// Win32 error conventions, but golint insists on CamelCase.
const (
	CoEClassstring     = syscall.Errno(0x800401F3) // Invalid class string
	ErrorNoNetwork     = syscall.Errno(1222)       // The network is not present or not started
	ErrorBadPathname   = syscall.Errno(161)        // The specified path is invalid
	ErrorInvalidObject = syscall.Errno(0x800710D8) // The object identifier does not represent a valid object
)

type layer struct {
	ID   string
	Path string
}

type defConfig struct {
	DefFile string
}

type portBinding struct {
	Protocol     string
	InternalPort int
	ExternalPort int
}

type natSettings struct {
	Name         string
	PortBindings []portBinding
}

type networkConnection struct {
	NetworkName string
	Nat         natSettings
}
type networkSettings struct {
	MacAddress string
}

type device struct {
	DeviceType string
	Connection interface{}
	Settings   interface{}
}

type mappedDir struct {
	HostPath      string
	ContainerPath string
	ReadOnly      bool
}

// TODO Windows: @darrenstahlmsft Add ProcessorCount
type containerInit struct {
	SystemType              string      // HCS requires this to be hard-coded to "Container"
	Name                    string      // Name of the container. We use the docker ID.
	Owner                   string      // The management platform that created this container
	IsDummy                 bool        // Used for development purposes.
	VolumePath              string      // Windows volume path for scratch space
	Devices                 []device    // Devices used by the container
	IgnoreFlushesDuringBoot bool        // Optimization hint for container startup in Windows
	LayerFolderPath         string      // Where the layer folders are located
	Layers                  []layer     // List of storage layers
	ProcessorWeight         uint64      `json:",omitempty"` // CPU Shares 0..10000 on Windows; where 0 will be omitted and HCS will default.
	ProcessorMaximum        int64       `json:",omitempty"` // CPU maximum usage percent 1..100
	StorageIOPSMaximum      uint64      `json:",omitempty"` // Maximum Storage IOPS
	StorageBandwidthMaximum uint64      `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second
	StorageSandboxSize      uint64      `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller
	MemoryMaximumInMB       int64       `json:",omitempty"` // Maximum memory available to the container in Megabytes
	HostName                string      // Hostname
	MappedDirectories       []mappedDir // List of mapped directories (volumes/mounts)
	SandboxPath             string      // Location of unmounted sandbox (used for Hyper-V containers)
	HvPartition             bool        // True if it a Hyper-V Container
	EndpointList            []string    // List of networking endpoints to be attached to container
}

// defaultOwner is a tag passed to HCS to allow it to differentiate between
// container creator management stacks. We hard code "docker" in the case
// of docker.
const defaultOwner = "docker"

// Create is the entrypoint to create a container from a spec, and if successfully
// created, start it too.
func (clnt *client) Create(containerID string, spec Spec, options ...CreateOption) error {
	logrus.Debugln("LCD client.Create() with spec", spec)

	cu := &containerInit{
		SystemType: "Container",
		Name:       containerID,
		Owner:      defaultOwner,

		VolumePath:              spec.Root.Path,
		IgnoreFlushesDuringBoot: spec.Windows.FirstStart,
		LayerFolderPath:         spec.Windows.LayerFolder,
		HostName:                spec.Hostname,
	}

	if spec.Windows.Networking != nil {
		cu.EndpointList = spec.Windows.Networking.EndpointList
	}

	if spec.Windows.Resources != nil {
		if spec.Windows.Resources.CPU != nil {
			if spec.Windows.Resources.CPU.Shares != nil {
				cu.ProcessorWeight = *spec.Windows.Resources.CPU.Shares
			}
			if spec.Windows.Resources.CPU.Percent != nil {
				cu.ProcessorMaximum = *spec.Windows.Resources.CPU.Percent * 100 // ProcessorMaximum is a value between 1 and 10000
			}
		}
		if spec.Windows.Resources.Memory != nil {
			if spec.Windows.Resources.Memory.Limit != nil {
				cu.MemoryMaximumInMB = *spec.Windows.Resources.Memory.Limit / 1024 / 1024
			}
		}
		if spec.Windows.Resources.Storage != nil {
			if spec.Windows.Resources.Storage.Bps != nil {
				cu.StorageBandwidthMaximum = *spec.Windows.Resources.Storage.Bps
			}
			if spec.Windows.Resources.Storage.Iops != nil {
				cu.StorageIOPSMaximum = *spec.Windows.Resources.Storage.Iops
			}
			if spec.Windows.Resources.Storage.SandboxSize != nil {
				cu.StorageSandboxSize = *spec.Windows.Resources.Storage.SandboxSize
			}
		}
	}

	cu.HvPartition = (spec.Windows.HvRuntime != nil)

	// TODO Windows @jhowardmsft. FIXME post TP5.
	//	if spec.Windows.HvRuntime != nil {
	//		if spec.WIndows.HVRuntime.ImagePath != "" {
	//			cu.TBD = spec.Windows.HvRuntime.ImagePath
	//		}
	//	}

	if cu.HvPartition {
		cu.SandboxPath = filepath.Dir(spec.Windows.LayerFolder)
	} else {
		cu.VolumePath = spec.Root.Path
		cu.LayerFolderPath = spec.Windows.LayerFolder
	}

	for _, layerPath := range spec.Windows.LayerPaths {
		_, filename := filepath.Split(layerPath)
		g, err := hcsshim.NameToGuid(filename)
		if err != nil {
			return err
		}
		cu.Layers = append(cu.Layers, layer{
			ID:   g.ToString(),
			Path: layerPath,
		})
	}

	// Add the mounts (volumes, bind mounts etc) to the structure
	mds := make([]mappedDir, len(spec.Mounts))
	for i, mount := range spec.Mounts {
		mds[i] = mappedDir{
			HostPath:      mount.Source,
			ContainerPath: mount.Destination,
			ReadOnly:      mount.Readonly}
	}
	cu.MappedDirectories = mds

	// TODO Windows: vv START OF TP4 BLOCK OF CODE. REMOVE ONCE TP4 IS NO LONGER SUPPORTED
	if hcsshim.IsTP4() &&
		spec.Windows.Networking != nil &&
		spec.Windows.Networking.Bridge != "" {
		// Enumerate through the port bindings specified by the user and convert
		// them into the internal structure matching the JSON blob that can be
		// understood by the HCS.
		var pbs []portBinding
		for i, v := range spec.Windows.Networking.PortBindings {
			proto := strings.ToUpper(i.Proto())
			if proto != "TCP" && proto != "UDP" {
				return fmt.Errorf("invalid protocol %s", i.Proto())
			}

			if len(v) > 1 {
				return fmt.Errorf("Windows does not support more than one host port in NAT settings")
			}

			for _, v2 := range v {
				var (
					iPort, ePort int
					err          error
				)
				if len(v2.HostIP) != 0 {
					return fmt.Errorf("Windows does not support host IP addresses in NAT settings")
				}
				if ePort, err = strconv.Atoi(v2.HostPort); err != nil {
					return fmt.Errorf("invalid container port %s: %s", v2.HostPort, err)
				}
				if iPort, err = strconv.Atoi(i.Port()); err != nil {
					return fmt.Errorf("invalid internal port %s: %s", i.Port(), err)
				}
				if iPort < 0 || iPort > 65535 || ePort < 0 || ePort > 65535 {
					return fmt.Errorf("specified NAT port is not in allowed range")
				}
				pbs = append(pbs,
					portBinding{ExternalPort: ePort,
						InternalPort: iPort,
						Protocol:     proto})
			}
		}

		dev := device{
			DeviceType: "Network",
			Connection: &networkConnection{
				NetworkName: spec.Windows.Networking.Bridge,
				Nat: natSettings{
					Name:         defaultContainerNAT,
					PortBindings: pbs,
				},
			},
		}

		if spec.Windows.Networking.MacAddress != "" {
			windowsStyleMAC := strings.Replace(
				spec.Windows.Networking.MacAddress, ":", "-", -1)
			dev.Settings = networkSettings{
				MacAddress: windowsStyleMAC,
			}
		}
		cu.Devices = append(cu.Devices, dev)
	} else {
		logrus.Debugln("No network interface")
	}
	// TODO Windows: ^^ END OF TP4 BLOCK OF CODE. REMOVE ONCE TP4 IS NO LONGER SUPPORTED

	configurationb, err := json.Marshal(cu)
	if err != nil {
		return err
	}

	configuration := string(configurationb)

	// TODO Windows TP5 timeframe. Remove when TP4 is no longer supported.
	// The following a workaround for Windows TP4 which has a networking
	// bug which fairly frequently returns an error. Back off and retry.
	if !hcsshim.IsTP4() {
		if err := hcsshim.CreateComputeSystem(containerID, configuration); err != nil {
			return err
		}
	} else {
		maxAttempts := 5
		for i := 1; i <= maxAttempts; i++ {
			err = hcsshim.CreateComputeSystem(containerID, configuration)
			if err == nil {
				break
			}

			if herr, ok := err.(*hcsshim.HcsError); ok {
				if herr.Err != syscall.ERROR_NOT_FOUND && // Element not found
					herr.Err != syscall.ERROR_FILE_NOT_FOUND && // The system cannot find the file specified
					herr.Err != ErrorNoNetwork && // The network is not present or not started
					herr.Err != ErrorBadPathname && // The specified path is invalid
					herr.Err != CoEClassstring && // Invalid class string
					herr.Err != ErrorInvalidObject { // The object identifier does not represent a valid object
					logrus.Debugln("Failed to create temporary container ", err)
					return err
				}
				logrus.Warnf("Invoking Windows TP4 retry hack (%d of %d)", i, maxAttempts-1)
				time.Sleep(50 * time.Millisecond)
			}
		}
	}

	// Construct a container object for calling start on it.
	container := &container{
		containerCommon: containerCommon{
			process: process{
				processCommon: processCommon{
					containerID:  containerID,
					client:       clnt,
					friendlyName: InitFriendlyName,
				},
				commandLine: strings.Join(spec.Process.Args, " "),
			},
			processes: make(map[string]*process),
		},
		ociSpec: spec,
	}

	container.options = options
	for _, option := range options {
		if err := option.Apply(container); err != nil {
			logrus.Error(err)
		}
	}

	// Call start, and if it fails, delete the container from our
	// internal structure, and also keep HCS in sync by deleting the
	// container there.
	logrus.Debugf("Create() id=%s, Calling start()", containerID)
	if err := container.start(); err != nil {
		clnt.deleteContainer(containerID)
		return err
	}

	logrus.Debugf("Create() id=%s completed successfully", containerID)
	return nil

}

// AddProcess is the handler for adding a process to an already running
// container. It's called through docker exec.
func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAdd Process) error {

	clnt.lock(containerID)
	defer clnt.unlock(containerID)
	container, err := clnt.getContainer(containerID)
	if err != nil {
		return err
	}

	createProcessParms := hcsshim.CreateProcessParams{
		EmulateConsole: procToAdd.Terminal,
		ConsoleSize:    procToAdd.InitialConsoleSize,
	}

	// Take working directory from the process to add if it is defined,
	// otherwise take from the first process.
	if procToAdd.Cwd != "" {
		createProcessParms.WorkingDirectory = procToAdd.Cwd
	} else {
		createProcessParms.WorkingDirectory = container.ociSpec.Process.Cwd
	}

	// Configure the environment for the process
	createProcessParms.Environment = setupEnvironmentVariables(procToAdd.Env)
	createProcessParms.CommandLine = strings.Join(procToAdd.Args, " ")

	logrus.Debugf("commandLine: %s", createProcessParms.CommandLine)

	// Start the command running in the container. Note we always tell HCS to
	// create stdout as it's required regardless of '-i' or '-t' options, so that
	// docker can always grab the output through logs. We also tell HCS to always
	// create stdin, even if it's not used - it will be closed shortly. Stderr
	// is only created if it we're not -t.
	var stdout, stderr io.ReadCloser
	var pid uint32
	iopipe := &IOPipe{Terminal: procToAdd.Terminal}
	pid, iopipe.Stdin, stdout, stderr, err = hcsshim.CreateProcessInComputeSystem(
		containerID,
		true,
		true,
		!procToAdd.Terminal,
		createProcessParms)
	if err != nil {
		logrus.Errorf("AddProcess %s CreateProcessInComputeSystem() failed %s", containerID, err)
		return err
	}

	// Convert io.ReadClosers to io.Readers
	if stdout != nil {
		iopipe.Stdout = openReaderFromPipe(stdout)
	}
	if stderr != nil {
		iopipe.Stderr = openReaderFromPipe(stderr)
	}

	// Add the process to the containers list of processes
	container.processes[processFriendlyName] =
		&process{
			processCommon: processCommon{
				containerID:  containerID,
				friendlyName: processFriendlyName,
				client:       clnt,
				systemPid:    pid,
			},
			commandLine: createProcessParms.CommandLine,
		}

	// Make sure the lock is not held while calling back into the daemon
	clnt.unlock(containerID)

	// Tell the engine to attach streams back to the client
	if err := clnt.backend.AttachStreams(processFriendlyName, *iopipe); err != nil {
		return err
	}

	// Lock again so that the defer unlock doesn't fail. (I really don't like this code)
	clnt.lock(containerID)

	// Spin up a go routine waiting for exit to handle cleanup
	go container.waitExit(pid, processFriendlyName, false)

	return nil
}

// Signal handles `docker stop` on Windows. While Linux has support for
// the full range of signals, signals aren't really implemented on Windows.
// We fake supporting regular stop and -9 to force kill.
func (clnt *client) Signal(containerID string, sig int) error {
	var (
		cont *container
		err  error
	)

	// Get the container as we need it to find the pid of the process.
	clnt.lock(containerID)
	defer clnt.unlock(containerID)
	if cont, err = clnt.getContainer(containerID); err != nil {
		return err
	}

	logrus.Debugf("lcd: Signal() containerID=%s sig=%d pid=%d", containerID, sig, cont.systemPid)
	context := fmt.Sprintf("Signal: sig=%d pid=%d", sig, cont.systemPid)

	if syscall.Signal(sig) == syscall.SIGKILL {
		// Terminate the compute system
		if err := hcsshim.TerminateComputeSystem(containerID, hcsshim.TimeoutInfinite, context); err != nil {
			logrus.Errorf("Failed to terminate %s - %q", containerID, err)
		}

	} else {
		// Terminate Process
		if err = hcsshim.TerminateProcessInComputeSystem(containerID, cont.systemPid); err != nil {
			logrus.Warnf("Failed to terminate pid %d in %s: %q", cont.systemPid, containerID, err)
			// Ignore errors
			err = nil
		}

		// Shutdown the compute system
		if err := hcsshim.ShutdownComputeSystem(containerID, hcsshim.TimeoutInfinite, context); err != nil {
			logrus.Errorf("Failed to shutdown %s - %q", containerID, err)
		}
	}
	return nil
}

// Resize handles a CLI event to resize an interactive docker run or docker exec
// window.
func (clnt *client) Resize(containerID, processFriendlyName string, width, height int) error {
	// Get the libcontainerd container object
	clnt.lock(containerID)
	defer clnt.unlock(containerID)
	cont, err := clnt.getContainer(containerID)
	if err != nil {
		return err
	}

	if processFriendlyName == InitFriendlyName {
		logrus.Debugln("Resizing systemPID in", containerID, cont.process.systemPid)
		return hcsshim.ResizeConsoleInComputeSystem(containerID, cont.process.systemPid, height, width)
	}

	for _, p := range cont.processes {
		if p.friendlyName == processFriendlyName {
			logrus.Debugln("Resizing exec'd process", containerID, p.systemPid)
			return hcsshim.ResizeConsoleInComputeSystem(containerID, p.systemPid, height, width)
		}
	}

	return fmt.Errorf("Resize could not find containerID %s to resize", containerID)

}

// Pause handles pause requests for containers
func (clnt *client) Pause(containerID string) error {
	return errors.New("Windows: Containers cannot be paused")
}

// Resume handles resume requests for containers
func (clnt *client) Resume(containerID string) error {
	return errors.New("Windows: Containers cannot be paused")
}

// Stats handles stats requests for containers
func (clnt *client) Stats(containerID string) (*Stats, error) {
	return nil, errors.New("Windows: Stats not implemented")
}

// Restore is the handler for restoring a container
func (clnt *client) Restore(containerID string, unusedOnWindows ...CreateOption) error {
	// TODO Windows: Implement this. For now, just tell the backend the container exited.
	logrus.Debugf("lcd Restore %s", containerID)
	return clnt.backend.StateChanged(containerID, StateInfo{
		State:    StateExit,
		ExitCode: 1 << 31,
	})
}

// GetPidsForContainer returns a list of process IDs running in a container.
// Although implemented, this is not used in Windows.
func (clnt *client) GetPidsForContainer(containerID string) ([]int, error) {
	var pids []int
	clnt.lock(containerID)
	defer clnt.unlock(containerID)
	cont, err := clnt.getContainer(containerID)
	if err != nil {
		return nil, err
	}

	// Add the first process
	pids = append(pids, int(cont.containerCommon.systemPid))
	// And add all the exec'd processes
	for _, p := range cont.processes {
		pids = append(pids, int(p.processCommon.systemPid))
	}
	return pids, nil
}

// Summary returns a summary of the processes running in a container.
// This is present in Windows to support docker top. In linux, the
// engine shells out to ps to get process information. On Windows, as
// the containers could be Hyper-V containers, they would not be
// visible on the container host. However, libcontainerd does have
// that information.
func (clnt *client) Summary(containerID string) ([]Summary, error) {
	var s []Summary
	clnt.lock(containerID)
	defer clnt.unlock(containerID)
	cont, err := clnt.getContainer(containerID)
	if err != nil {
		return nil, err
	}

	// Add the first process
	s = append(s, Summary{
		Pid:     cont.containerCommon.systemPid,
		Command: cont.ociSpec.Process.Args[0]})
	// And add all the exec'd processes
	for _, p := range cont.processes {
		s = append(s, Summary{
			Pid:     p.processCommon.systemPid,
			Command: p.commandLine})
	}
	return s, nil

}

// UpdateResources updates resources for a running container.
func (clnt *client) UpdateResources(containerID string, resources Resources) error {
	// Updating resource isn't supported on Windows
	// but we should return nil for enabling updating container
	return nil
}
