package com.example.m20_gamepad.network.models

import kotlinx.serialization.json.JsonObjectBuilder
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.putJsonObject
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * 构建 ASDU JSON 字符串的工具函数。
 *
 * 所有控制指令共用固定外层:
 * ```json
 * {"PatrolDevice": {"Type": int, "Command": int, "Time": "...", "Items": {}}}
 * ```
 */
object ControlCommands {

    private val timeFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())

    /** 当前时间字符串 */
    private fun now(): String = timeFormatter.format(Date())

    /** 构建 PatrolDevice 包裹的 JSON 字符串。Items 始终存在（可为空对象）。 */
    private fun buildAsdu(
        type: Int,
        command: Int,
        time: String = now(),
        itemsBuilder: JsonObjectBuilder.() -> Unit = {}
    ): String = buildJsonObject {
        putJsonObject("PatrolDevice") {
            put("Type", JsonPrimitive(type))
            put("Command", JsonPrimitive(command))
            put("Time", JsonPrimitive(time))
            putJsonObject("Items") {
                itemsBuilder()
            }
        }
    }.toString()

    // ---- 2.1 心跳 ----
    fun heartbeat(time: String = now()): String = buildAsdu(type = 100, command = 100, time = time)

    // ---- 2.2 使用模式切换 ----
    fun switchMode(mode: Int, time: String = now()): String = buildAsdu(
        type = 1101, command = 5, time = time
    ) {
        put("Mode", JsonPrimitive(mode))
    }

    // ---- 2.3 运动状态转换 ----
    fun motionControl(motionParam: Int, time: String = now()): String = buildAsdu(
        type = 2, command = 22, time = time
    ) {
        put("MotionParam", JsonPrimitive(motionParam))
    }

    // ---- 2.4 步态切换 ----
    fun switchGait(gaitParam: Int, time: String = now()): String = buildAsdu(
        type = 2, command = 23, time = time
    ) {
        put("GaitParam", JsonPrimitive(gaitParam))
    }

    // ---- 2.5 轴指令（常规模式） ----
    fun axisCommand(
        x: Double = 0.0, y: Double = 0.0, z: Double = 0.0,
        roll: Double = 0.0, pitch: Double = 0.0, yaw: Double = 0.0,
        time: String = now()
    ): String = buildAsdu(type = 2, command = 21, time = time) {
        put("X", JsonPrimitive(x))
        put("Y", JsonPrimitive(y))
        put("Z", JsonPrimitive(z))
        put("Roll", JsonPrimitive(roll))
        put("Pitch", JsonPrimitive(pitch))
        put("Yaw", JsonPrimitive(yaw))
    }

    // ---- 2.6 速度指令（导航模式） ----
    fun speedCommand(
        x: Double = 0.0, y: Double = 0.0, z: Double = 0.0,
        roll: Double = 0.0, pitch: Double = 0.0, yaw: Double = 0.0,
        time: String = now()
    ): String = buildAsdu(type = 2, command = 25, time = time) {
        put("X", JsonPrimitive(x))
        put("Y", JsonPrimitive(y))
        put("Z", JsonPrimitive(z))
        put("Roll", JsonPrimitive(roll))
        put("Pitch", JsonPrimitive(pitch))
        put("Yaw", JsonPrimitive(yaw))
    }

    // ---- 2.7 照明灯控制 ----
    fun lightControl(front: Int, back: Int, time: String = now()): String = buildAsdu(
        type = 1101, command = 2, time = time
    ) {
        put("Front", JsonPrimitive(front))
        put("Back", JsonPrimitive(back))
    }

    // ---- 2.8 自主充电 ----
    fun chargeControl(charge: Int, time: String = now()): String = buildAsdu(
        type = 2, command = 24, time = time
    ) {
        put("Charge", JsonPrimitive(charge))
    }

    // ---- 2.9 休眠模式设置 ----
    fun sleepSettings(sleep: Boolean, auto: Boolean, timeMinutes: Int, time: String = now()): String = buildAsdu(
        type = 1101, command = 6, time = time
    ) {
        put("Sleep", JsonPrimitive(sleep))
        put("Auto", JsonPrimitive(auto))
        put("Time", JsonPrimitive(timeMinutes))
    }

    // ---- 2.10 休眠状态查询 ----
    fun querySleepStatus(time: String = now()): String = buildAsdu(type = 1101, command = 7, time = time)

    // ---- 订阅状态上报 ----
    fun subscribeStatus(type: Int, command: Int, time: String = now()): String =
        buildAsdu(type = type, command = command, time = time)

    // ========== 常量 ==========

    // 运动状态常量
    const val MOTION_IDLE = 0
    const val MOTION_STAND = 1
    const val MOTION_DAMPING = 2
    const val MOTION_BOOT_DAMPING = 3
    const val MOTION_LIE_DOWN = 4
    const val MOTION_RL_CONTROL = 17

    // 步态常量
    const val GAIT_BASIC = 0x1001
    const val GAIT_STAIRS = 0x1003
    const val GAIT_FLAT_AGILE = 0x3002
    const val GAIT_STAIRS_AGILE = 0x3003

    // 使用模式常量
    const val MODE_NORMAL = 0
    const val MODE_NAVIGATION = 1
    const val MODE_ASSIST = 2

    // 订阅 Type/Command — 用于 subscribeStatus()
    val SUB_ERROR = Pair(1002, 3)
    val SUB_MOTION_CONTROL = Pair(1002, 4)
    val SUB_DEVICE = Pair(1002, 5)
    val SUB_BASIC = Pair(1002, 6)
}