package main

import (
	"github.com/elk-language/go-prompt"
	"strings"
)

type Action func(args []string)

type CommandArg struct {
	Name     string
	Action   Action
	Help     string
	Children []CommandArg
}

var commandIssues = CommandArg{Name: "issues"}

func option(name string, children ...CommandArg) CommandArg {
	return command(name, nil, children...)
}

func command(name string, action Action, children ...CommandArg) CommandArg {
	return CommandArg{
		Name:     name,
		Action:   action,
		Children: children,
	}
}

func (arg CommandArg) WithHelp(help string) CommandArg {
	arg.Help = help
	return arg
}

var CommandTree = []CommandArg{
	option("list",
		command("issues", ActionListIssues).WithHelp("List all issues in the current sprint"),
		command("boards", ActionListBoards).WithHelp("List all boards in the current project"),
		//command("sprints", ActionListIssues).WithHelp("List all issues in the current sprint"),
		//option("open", option("issues")),
		//option("closed", option("issues")),
		command("projects", ActionListProjects).WithHelp("List all projects"),
	).WithHelp("List things"),
	option("use",
		command("project", ActionUseProject).WithHelp("Use project [project key]"),
		command("board", ActionUseBoard).WithHelp("Use board [board id]"),
		option("current", command("sprint", ActionUseCurrentSprint).WithHelp("Use the current sprint")),
	).WithHelp("Select something for further commands"),
	//option("view",
	//	option("issue"),
	//	option("sprint"),
	//),
	command("exit", ActionExit).WithHelp("Exit jirashell"),
	command("logout", ActionLogout).WithHelp("Logout from Jira"),
}

func getCommandFor(parts []string, tree []CommandArg) (*CommandArg, []string) {
	for _, arg := range tree {
		if arg.Name == parts[0] {
			if len(parts) == 1 {
				return &arg, []string{}
			} else {
				result, args := getCommandFor(parts[1:], arg.Children)
				if result != nil {
					return result, args
				} else {
					return &arg, parts[1:]
				}
			}
		}
	}
	return nil, nil
}

func GetCommand(cmdline string) (*CommandArg, []string) {
	commandParts := strings.Split(cmdline, " ")
	command, args := getCommandFor(commandParts, CommandTree)
	if command == nil || command.Action == nil {
		return nil, nil
	}
	return command, args
}

func GetSuggestionsForPart(parts []string, tree []CommandArg, suggests []prompt.Suggest) []prompt.Suggest {
	for _, option := range tree {
		if len(parts) == 0 {
			suggests = append(suggests, prompt.Suggest{
				Text:        option.Name,
				Description: option.Help,
			})
		} else if option.Name == parts[0] {
			suggests = GetSuggestionsForPart(parts[1:], option.Children, suggests)
		} else if len(parts) == 1 {
			if strings.HasPrefix(option.Name, parts[0]) {
				suggests = append(suggests, prompt.Suggest{
					Text:        option.Name,
					Description: option.Help,
				})
			}
		}
	}
	return suggests
}

func GetSuggestionsFor(command string) []prompt.Suggest {
	commandParts := strings.Split(command, " ")
	return GetSuggestionsForPart(commandParts, CommandTree, []prompt.Suggest{})
}