package main


import (
	"bufio"
	"fmt"
	"path"
	"os"
	"os/exec"
	"os/user"

	"git.tilde.town/tildetown/town/towndb"
)

func confirmRename() {
	fmt.Println("this will kill all of the user's current processes. if you're doing this live you should give them a good contact if things break")

	var text string

	for text != "y\n" {
		fmt.Print("enter 'y' to continue: ")
		reader := bufio.NewReader(os.Stdin)
		text, _ = reader.ReadString('\n')
	}
}

func killUser(name string) (err error) {
	cmd := exec.Command("pkill", "-SIGKILL", "-u", name)
	cmd.Stderr = os.Stderr

	if err = cmd.Run(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if exiterr.ExitCode() == 1 {
				return nil
			}
		}

		return err
	}

	return nil
}

func usermod(old_name string, new_name string) (err error) {
	cmd := exec.Command(
		"usermod",
		"-l", new_name,
		"-m",
		"-d", path.Join("/home", new_name),
		old_name,
	)
	cmd.Stderr = os.Stderr

	if err = cmd.Run(); err != nil {
		return err
	}

	cmd = exec.Command("groupmod", "-n", new_name, old_name)
	cmd.Stderr = os.Stderr

	if err = cmd.Run(); err != nil {
		return err
	}

	return
}

func renameDb(old_name string, new_name string) (err error) {
	db, err := towndb.ConnectDB()
	if err != nil {
		return err
	}

	err = towndb.RenameUser(db, old_name, new_name)
	if err != nil {
		return err
	}

	return nil
}

func quit(text string) {
	fmt.Println(text)
	os.Exit(1)
}

func main() {
	if len(os.Args) != 3 {
		quit("usage: rename username new_username")
	}

	old_name := os.Args[1]
	new_name := os.Args[2]

	user, err := user.Current()
	if err != nil {
		quit(fmt.Sprintf("couldn't get user info: %v", err))
	}

	if user.Uid != "0" {
		quit("must be run as root")
	}

	confirmRename()

	if err := killUser(old_name); err != nil {
		quit(fmt.Sprintf("pkill failed: %v", err))
	}

	fmt.Println("killed old processes")

	if err := usermod(old_name, new_name); err != nil {
		quit(fmt.Sprintf("unix user rename failed: %v", err))
	}

	fmt.Println("renamed unix user")

	if err := renameDb(old_name, new_name); err != nil {
		fmt.Println(fmt.Sprintf("couldn't rename user in /town/var/town.db: %v", err))
		fmt.Println("something might be amiss with town.db")
	} else {
		fmt.Println("renamed user in /town/var/town.db")
	}
}
