package manager

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"text/template"

	"git.rootprojects.org/root/go-serviceman/manager/static"
	"git.rootprojects.org/root/go-serviceman/service"
)

const (
	srvExt      = ".plist"
	srvSysPath  = "/Library/LaunchDaemons"
	srvUserPath = "Library/LaunchAgents"
)

var srvLen int

func init() {
	srvLen = len(srvExt)
}

func start(system bool, home string, name string) error {
	sys, user, err := getMatchingSrvs(home, name)
	if nil != err {
		return err
	}

	var service string
	if system {
		service, err = getOneSysSrv(sys, user, name)
		if nil != err {
			return err
		}
		service = filepath.Join(srvSysPath, service)
	} else {
		service, err = getOneUserSrv(home, sys, user, name)
		if nil != err {
			return err
		}
		service = filepath.Join(home, srvUserPath, service)
	}

	cmds := []Runnable{
		Runnable{
			Exec: "launchctl",
			Args: []string{"unload", "-w", service},
			Must: false,
		},
		Runnable{
			Exec: "launchctl",
			Args: []string{"load", "-w", service},
			Must: true,
		},
	}

	cmds = adjustPrivs(system, cmds)

	fmt.Println()
	fmt.Println("Starting launchd service...")
	for i := range cmds {
		exe := cmds[i]
		fmt.Println("\t" + exe.String())
		err := exe.Run()
		if nil != err {
			return err
		}
	}
	fmt.Println()

	return nil
}

func install(c *service.Service) error {
	// Darwin-specific config options
	if c.PrivilegedPorts {
		if !c.System {
			return fmt.Errorf("You must use root-owned LaunchDaemons (not user-owned LaunchAgents) to use priveleged ports on OS X")
		}
	}
	plistDir := srvSysPath
	if !c.System {
		plistDir = filepath.Join(c.Home, srvUserPath)
	}

	// Check paths first
	err := os.MkdirAll(filepath.Dir(plistDir), 0755)
	if nil != err {
		return err
	}

	// Create service file from template
	b, err := static.ReadFile("dist/Library/LaunchDaemons/_rdns_.plist.tmpl")
	if err != nil {
		return err
	}
	s := string(b)
	rw := &bytes.Buffer{}
	// not sure what the template name does, but whatever
	tmpl, err := template.New("service").Parse(s)
	if err != nil {
		return err
	}
	err = tmpl.Execute(rw, c)
	if nil != err {
		return err
	}

	// Write the file out
	// TODO rdns
	plistName := c.ReverseDNS + ".plist"
	plistPath := filepath.Join(plistDir, plistName)
	if err := ioutil.WriteFile(plistPath, rw.Bytes(), 0644); err != nil {
		return fmt.Errorf("Error writing %s: %v", plistPath, err)
	}

	// TODO --no-start
	err = start(c.System, c.Home, c.ReverseDNS)
	if nil != err {
		fmt.Printf("If things don't go well you should be able to get additional logging from launchctl:\n")
		fmt.Printf("\tsudo launchctl log level debug\n")
		fmt.Printf("\ttail -f /var/log/system.log\n")
		return err
	}

	fmt.Printf("Added and started '%s' as a launchctl service.\n", c.Name)
	return nil
}
