package a_init

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"wdd.io/agent-go/a_agent"
	"wdd.io/agent-go/a_executor"
	"wdd.io/agent-go/a_init/bastion_init"
	"wdd.io/agent-go/a_status"
)

/*
  完全离线模式
  交互模式 手动运行 接受输入并且执行指令 类似于cli

  1. 环境信息检测打印输出

  2. 接受用户输入 执行指令

  3. 功能
	3.1 安装docker
    3.2 安装docker-compose
    3.3 安装minio
    3.4 安装rabbitmq
    3.5 安装kubernetes
*/

var AllFunctionCache = &bastion_init.Trie{}

const (
	InstallDocker        = "docker"
	InstallDockerCompose = "dockercompose"
	InstallHarbor        = "harbor"
	InstallDefaultSsh    = "ssh"
	DisableSwap          = "swap"
	DisableSelinux       = "selinux"
	DisableFirewall      = "firewall"
	ModifySysConfig      = "sysconfig"
	ModifyDockerConfig   = "dockerconfig"
	InstallMinio         = "minio"
	RemoveDocker         = "removedocker"
	Exit                 = "exit"
	Help                 = "help"
)

// BastionModeInit 堡垒机模式 完全离线模式
func BastionModeInit() {

	// Build For Operator
	bastionAgentServerInfo := &a_agent.AgentServerInfo{
		ServerName:      "BastionSingle",
		ServerIPPbV4:    "",
		ServerIPInV4:    "",
		ServerIPPbV6:    "",
		ServerIPInV6:    "",
		Location:        "Bastion",
		Provider:        "Bastion",
		ManagePort:      "22",
		CPUCore:         "",
		CPUBrand:        "",
		OSInfo:          "",
		OSKernelInfo:    "",
		TCPControl:      "",
		Virtualization:  "",
		Platform:        "",
		PlatformFamily:  "",
		PlatformVersion: "",
		KernelVersion:   "",
		KernelArch:      "",
		IoSpeed:         "",
		MemoryTotal:     "",
		DiskTotal:       "",
		DiskUsage:       "",
		Comment:         "",
		MachineID:       "",
		AgentVersion:    "",
		AgentTopicName:  "BastionNode",
	}

	// build for bastion mode operator
	// re-get agentInfo from status module
	agentInfo := a_status.ReportAgentInfo()
	refreshAgentInfoByStatusInfo(agentInfo, bastionAgentServerInfo)

	// build operator cache
	buildAgentOsOperator(agentInfo, bastionAgentServerInfo)

	// 缓存此内容
	a_agent.AgentServerInfoCache = bastionAgentServerInfo
	agentOperator := a_executor.AgentOsOperatorCache

	// build for all functions
	buildBastionModeFunction()

	// build for function arguments list
	//var funcArgsList []string

	reader := bufio.NewReader(os.Stdin)
	bastion_init.PrintBastionHelp()

	fmt.Println()
	fmt.Print("enter ==> ")

	text, _ := reader.ReadString('\n')
	text = strings.TrimSpace(text)
	inputCommand := uniformInputCommand(text)
	fmt.Println("inputCommand: ", inputCommand)
	fmt.Println()

	// execute the function
	switch inputCommand {
	case InstallDefaultSsh:
		beautifulPrintExeResult(agentOperator.InstallDefaultSshBastion())
	case DisableSwap:
		beautifulPrintExeResult(agentOperator.DisableSwapBastion())
	case DisableSelinux:
		beautifulPrintExeResult(agentOperator.DisableSelinuxBastion())
	case DisableFirewall:
		beautifulPrintExeResult(agentOperator.DisableFirewallBastion())
	case ModifySysConfig:
		beautifulPrintExeResult(agentOperator.ModifySysConfigBastion())
	case InstallDocker:
		beautifulPrintExeResult(agentOperator.InstallDockerBastion())
	case ModifyDockerConfig:
		beautifulPrintExeResult(agentOperator.ModifyDockerConfigBastion())
	case InstallDockerCompose:
		beautifulPrintExeResult(agentOperator.InstallDockerComposeBastion())
	case InstallMinio:
		agentOperator.InstallMinioBastion()
	case InstallHarbor:
		beautifulPrintExeResult(agentOperator.InstallHarborBastion())
	case RemoveDocker:
		beautifulPrintExeResult(agentOperator.RemoveDockerBastion())
	case Exit:
		os.Exit(0)
	case Help:
		bastion_init.PrintBastionHelp()
	default:
		fmt.Println("inputCommand is not exist ! Please input again")
	}

}

func beautifulPrintExeResult(resultOk bool, result []string) {
	fmt.Println()
	if resultOk {
		fmt.Println("execute SUCCESS")
	} else {
		fmt.Println("execute FAIL")
	}
	for _, s := range result {
		fmt.Println(s)
	}
	fmt.Println()
}

func buildBastionModeFunction() {
	// build the tree search node
	log.Info("build the tree search node")

	tcc := bastion_init.NewTrie()
	tcc.Insert(InstallDocker)
	tcc.Insert(InstallDockerCompose)
	tcc.Insert(InstallMinio)
	tcc.Insert(InstallDefaultSsh)
	tcc.Insert(DisableSwap)
	tcc.Insert(DisableSelinux)
	tcc.Insert(DisableFirewall)
	tcc.Insert(ModifySysConfig)
	tcc.Insert(ModifyDockerConfig)
	tcc.Insert(InstallHarbor)
	tcc.Insert(RemoveDocker)
	tcc.Insert(Help)
	tcc.Insert(Exit)

	AllFunctionCache = tcc
}

// uniformInputCommand 归一化输入的命令
func uniformInputCommand(inputString string) string {

	findClosestWord, err := bastion_init.FindClosestWord(AllFunctionCache, inputString)
	if err != nil {
		log.ErrorF("inputString error: %s", err.Error())
	}

	return findClosestWord
}
