package daemon

import (
	"fmt"
	"path/filepath"
	"sort"
	"strconv"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/container"
	"github.com/docker/docker/oci"
	"github.com/docker/libnetwork"
	"github.com/opencontainers/runtime-spec/specs-go"
)

func setResources(s *specs.Spec, r containertypes.Resources) error {
	mem := getMemoryResources(r)
	s.Solaris.CappedMemory = &mem

	capCPU := getCPUResources(r)
	s.Solaris.CappedCPU = &capCPU

	return nil
}

func setUser(s *specs.Spec, c *container.Container) error {
	uid, gid, additionalGids, err := getUser(c, c.Config.User)
	if err != nil {
		return err
	}
	s.Process.User.UID = uid
	s.Process.User.GID = gid
	s.Process.User.AdditionalGids = additionalGids
	return nil
}

func getUser(c *container.Container, username string) (uint32, uint32, []uint32, error) {
	return 0, 0, nil, nil
}

func (daemon *Daemon) getRunzAnet(ep libnetwork.Endpoint) (specs.Anet, error) {
	var (
		linkName  string
		lowerLink string
		defRouter string
	)

	epInfo := ep.Info()
	if epInfo == nil {
		return specs.Anet{}, fmt.Errorf("invalid endpoint")
	}

	nw, err := daemon.GetNetworkByName(ep.Network())
	if err != nil {
		return specs.Anet{}, fmt.Errorf("Failed to get network %s: %v", ep.Network(), err)
	}

	// Evaluate default router, linkname and lowerlink for interface endpoint
	switch nw.Type() {
	case "bridge":
		defRouter = epInfo.Gateway().String()
		linkName = "net0" // Should always be net0 for a container

		// TODO We construct lowerlink here exactly as done for solaris bridge
		// initialization. Need modular code to reuse.
		options := nw.Info().DriverOptions()
		nwName := options["com.docker.network.bridge.name"]
		lastChar := nwName[len(nwName)-1:]
		if _, err = strconv.Atoi(lastChar); err != nil {
			lowerLink = nwName + "_0"
		} else {
			lowerLink = nwName
		}

	case "overlay":
		defRouter = ""
		linkName = "net1"

		// TODO Follows generateVxlanName() in solaris overlay.
		id := nw.ID()
		if len(nw.ID()) > 12 {
			id = nw.ID()[:12]
		}
		lowerLink = "vx_" + id + "_0"
	}

	runzanet := specs.Anet{
		Linkname:          linkName,
		Lowerlink:         lowerLink,
		Allowedaddr:       epInfo.Iface().Address().String(),
		Configallowedaddr: "true",
		Defrouter:         defRouter,
		Linkprotection:    "mac-nospoof, ip-nospoof",
		Macaddress:        epInfo.Iface().MacAddress().String(),
	}

	return runzanet, nil
}

func (daemon *Daemon) setNetworkInterface(s *specs.Spec, c *container.Container) error {
	var anets []specs.Anet

	sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID)
	if err != nil {
		return fmt.Errorf("Could not obtain sandbox for container")
	}

	// Populate interfaces required for each endpoint
	for _, ep := range sb.Endpoints() {
		runzanet, err := daemon.getRunzAnet(ep)
		if err != nil {
			return fmt.Errorf("Failed to get interface information for endpoint %d: %v", ep.ID(), err)
		}
		anets = append(anets, runzanet)
	}

	s.Solaris.Anet = anets
	if anets != nil {
		s.Solaris.Milestone = "svc:/milestone/container:default"
	}
	return nil
}

func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container) error {
	linkedEnv, err := daemon.setupLinkedContainers(c)
	if err != nil {
		return err
	}
	s.Root = specs.Root{
		Path:     filepath.Dir(c.BaseFS),
		Readonly: c.HostConfig.ReadonlyRootfs,
	}
	rootUID, rootGID := daemon.GetRemappedUIDGID()
	if err := c.SetupWorkingDirectory(rootUID, rootGID); err != nil {
		return err
	}
	cwd := c.Config.WorkingDir
	s.Process.Args = append([]string{c.Path}, c.Args...)
	s.Process.Cwd = cwd
	s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
	s.Process.Terminal = c.Config.Tty
	s.Hostname = c.FullHostname()

	return nil
}

func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
	s := oci.DefaultSpec()
	if err := daemon.populateCommonSpec(&s, c); err != nil {
		return nil, err
	}

	if err := setResources(&s, c.HostConfig.Resources); err != nil {
		return nil, fmt.Errorf("runtime spec resources: %v", err)
	}

	if err := setUser(&s, c); err != nil {
		return nil, fmt.Errorf("spec user: %v", err)
	}

	if err := daemon.setNetworkInterface(&s, c); err != nil {
		return nil, err
	}

	if err := daemon.setupIpcDirs(c); err != nil {
		return nil, err
	}

	ms, err := daemon.setupMounts(c)
	if err != nil {
		return nil, err
	}
	ms = append(ms, c.IpcMounts()...)
	tmpfsMounts, err := c.TmpfsMounts()
	if err != nil {
		return nil, err
	}
	ms = append(ms, tmpfsMounts...)
	sort.Sort(mounts(ms))

	return (*specs.Spec)(&s), nil
}

// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
// It will do nothing on non-Linux platform
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
	return
}
