package main

import (
	"encoding/json"
	"time"

	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
	"hnyfkj.com.cn/rtu/linux/utils/shell"
)

var (
	rpc_ping = "executor.ping"
	rpc_exec = "executor.exec"
	rpc_stop = "executor.interrupt"
	rpc_quit = "executor.close"
)

// 是否串行执行
func (c *MQTTCoupler) needSerialize(method string) bool {
	switch method {
	case rpc_ping, rpc_stop:
		return false
	case rpc_exec, rpc_quit:
		return true
	default:
		return true
	}
}

// 是否控制指令
func (c *MQTTCoupler) isCtrlCommand(method string) bool {
	switch method {
	case rpc_ping, rpc_stop, rpc_quit:
		return true
	case rpc_exec:
		return false
	default:
		return false
	}
}

// 一次心跳检测
func (c *MQTTCoupler) ping() (*jsonrpc2.Response, error) {
	params := struct {
		ClientID string `json:"client_id"`
	}{
		ClientID: c.clientID,
	}

	return c.doCmd(rpc_ping, params)
}

// 用户请求命令
type ShellExecRequest struct {
	ClientID string `json:"client_id"`
	/// 命令执行的参数, 以匿名的方式嵌套
	shell.ExecuteParams
}

// 执行一条命令
func (c *MQTTCoupler) exec(
	cmd string) (*shell.ExecuteResult, error) {
	params := ShellExecRequest{
		ClientID: c.clientID,
		ExecuteParams: shell.ExecuteParams{
			HostFingerprint: c.machineID, // 调用者主机指纹
			Cmd:             cmd,
			Timeout:         int(shell.DefaultTimeout / time.Second),
		},
	}

	timeout := getCmdTimeoutByPrefix(cmd)
	if timeout > 0 {
		params.Timeout = timeout
	}

	exrs := shell.ExecuteResult{}
	resp, err := c.doCmd(rpc_exec, params)
	if err != nil {
		return &exrs, err
	}

	if resp.Error != nil { ////////////////// 错误应答
		exrs.ExitCode = int(resp.Error.Code)
		exrs.Stderr = resp.Error.Message
	} else if len(resp.Result) > 0 { //////// 正确应答
		if err := json.Unmarshal(resp.Result, &exrs); err != nil {
			exrs.ExitCode = 1
			exrs.Stderr = err.Error()
		}
	}
	return &exrs, nil
}

// 取出命令超时
func (c *MQTTCoupler) getCmdTimeout(params any) (int, bool) {
	switch v := params.(type) {
	case ShellExecRequest:
		return v.Timeout, true
	case *ShellExecRequest:
		if v == nil {
			return 0, false
		}
		return v.Timeout, true
	}
	return 0, false
}

// 中断当前执行
func (c *MQTTCoupler) stop() (*jsonrpc2.Response, error) {
	params := struct {
		ClientID string `json:"client_id"`
	}{
		ClientID: c.clientID,
	}

	return c.doCmd(rpc_stop, params)
}

// 关闭退出终端
func (c *MQTTCoupler) quit() (*jsonrpc2.Response, error) {
	params := struct {
		ClientID string `json:"client_id"`
	}{
		ClientID: c.clientID,
	}

	return c.doCmd(rpc_quit, params)
}
