// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"sort"
	"strconv"

	"github.com/olekukonko/tablewriter"

	"v.io/x/lib/cmdline"
)

// TODO(youngseokyoon): add a helper command that wraps "madb exec shell pm list users" to show all available users.
var cmdMadbUser = &cmdline.Command{
	Children:         []*cmdline.Command{cmdMadbUserSet, cmdMadbUserUnset, cmdMadbUserList, cmdMadbUserClearAll},
	Name:             "user",
	DontInheritFlags: true,
	Short:            "Manage default user settings for each device",
	Long: `
Manages default user settings for each device.

An Android device can have multiple user accounts, and each user account has a numeric ID associated
with it. Certain adb commands accept '--user <user_id>' as a parameter to allow specifying which of
the Android user account should be used when running the command. The default behavior when the
user ID is not provided varies by the adb command being run.

Some madb commands internally run these adb commands which accept the '--user' flag. You can let
madb use different user IDs for different devices by storing the default user ID for each device
using 'madb user set' command. If the default user ID is not set for a particular device, madb will
not provide the '--user' flag to the underlying adb command, and the current user will be used for
that device as a result.

Below is the list of madb commands which are affected by the default user ID settings:

    madb clear-data
    madb install
    madb start
    madb stop
    madb uninstall

For more details on how to obtain the user ID from an Android device, see 'madb user help set'.
`,
}

var cmdMadbUserSet = &cmdline.Command{
	Runner: subCommandRunnerWithFilepath{runMadbUserSet, getDefaultConfigFilePath},
	Name:   "set",
	Short:  "Set a default user ID to be used for the given device.",
	Long: `
Sets a default user ID to be used for the specified device, when there are multiple user accounts on
a single device.

The user IDs can be obtained using the 'adb [<device_serial>] shell pm list users' command.
Alternatively, you can use 'madb exec' if you want to specify the device with a nickname.
For example, running the following command:

    madb -n=MyPhone exec shell pm list users

will list the available users and their IDs on the MyPhone device.
Consider the following example output:

    [MyPhone]       Users:
    [MyPhone]               UserInfo{0:John Doe:13} running
    [MyPhone]               UserInfo{10:Work profile:30} running

There are two available users, "John Doe" and "Work profile". Each user is assigned a "user ID",
which appears on the left of the user name. In this case, the user ID of "John Doe" is "0", and the
user ID of the "Work profile" is "10".

To use the "Work profile" as the default user when running madb commands on this device, run the
following command:

    madb user set MyPhone 10

and then madb will use "Work profile" as the default user for device "MyPhone" in any of the
subsequence madb commands.
`,
	ArgsName: "<device_serial> <user_id>",
	ArgsLong: `
<device_serial> is the unique serial number for the device, which can be obtained from 'adb devices'.
<user_id> is one of the user IDs obtained from 'adb shell pm list users' command.
`,
}

func runMadbUserSet(env *cmdline.Env, args []string, filename string) error {
	// Check if the arguments are valid.
	if len(args) != 2 {
		return fmt.Errorf("There must be exactly two arguments.")
	}

	// TODO(youngseokyoon): make it possible to specify the device using its nickname or index.
	// Validate the device serial
	serial := args[0]
	if !isValidSerial(serial) {
		return fmt.Errorf("Not a valid device serial: %v", serial)
	}

	// Validate the user ID.
	userID := args[1]
	if id, err := strconv.Atoi(userID); err != nil || id < 0 {
		return fmt.Errorf("Not a valid user ID: %v", userID)
	}

	cfg, err := readConfig(filename)
	if err != nil {
		return err
	}

	// Add the <device_serial, user_id> mapping for the specified device.
	cfg.UserIDs[serial] = userID
	return writeConfig(cfg, filename)
}

var cmdMadbUserUnset = &cmdline.Command{
	Runner: subCommandRunnerWithFilepath{runMadbUserUnset, getDefaultConfigFilePath},
	Name:   "unset",
	Short:  "Unset the default user ID set by the 'madb user set' command.",
	Long: `
Unsets the default user ID assigned by the 'madb user set' command for the specified device.

Running this command without any device specifiers will unset the default users only for the
currently available devices and emulators, while keeping the default user IDs for the other devices.
`,
	ArgsName: "<device_serial>",
	ArgsLong: `
<device_serial> is the unique serial number for the device, which can be obtained from 'adb devices'.
`,
}

func runMadbUserUnset(env *cmdline.Env, args []string, filename string) error {
	// Check if the arguments are valid.
	if len(args) != 1 {
		return fmt.Errorf("There must be exactly one argument.")
	}

	// TODO(youngseokyoon): make it possible to specify the device using its nickname or index.
	// Validate the device serial
	serial := args[0]
	if !isValidSerial(serial) {
		return fmt.Errorf("Not a valid device serial: %v", serial)
	}

	cfg, err := readConfig(filename)
	if err != nil {
		return err
	}

	delete(cfg.UserIDs, serial)
	return writeConfig(cfg, filename)
}

var cmdMadbUserList = &cmdline.Command{
	Runner: subCommandRunnerWithFilepath{runMadbUserList, getDefaultConfigFilePath},
	Name:   "list",
	Short:  "List all the existing default user IDs.",
	Long: `
Lists all the currently stored default user IDs for devices.
`,
}

func runMadbUserList(env *cmdline.Env, args []string, filename string) error {
	cfg, err := readConfig(filename)
	if err != nil {
		return err
	}

	tw := tablewriter.NewWriter(os.Stdout)
	tw.SetHeader([]string{"Serial", "User ID"})
	tw.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
	tw.SetAutoFormatHeaders(false)
	tw.SetAlignment(tablewriter.ALIGN_LEFT)

	data := make([][]string, 0, len(cfg.UserIDs))
	for serial, userID := range cfg.UserIDs {
		data = append(data, []string{serial, userID})
	}

	sort.Sort(byFirstElement(data))

	for _, row := range data {
		tw.Append(row)
	}
	tw.Render()

	return nil
}

var cmdMadbUserClearAll = &cmdline.Command{
	Runner: subCommandRunnerWithFilepath{runMadbUserClearAll, getDefaultConfigFilePath},
	Name:   "clear-all",
	Short:  "Clear all the existing default user settings.",
	Long: `
Clears all the currently stored default user IDs for devices.

This command clears the default user IDs regardless of whether the device is currently connected or not.
`,
}

func runMadbUserClearAll(env *cmdline.Env, args []string, filename string) error {
	cfg, err := readConfig(filename)
	if err != nil {
		return err
	}

	cfg.UserIDs = make(map[string]string)
	return writeConfig(cfg, filename)
}
