# -*- coding: utf-8 -*-
"""
音·创 v3 内置的 Minecraft 结构生成插件中有关 BDX 结构操作的内容
"""

"""
版权所有 © 2026 金羿、玉衡Alioth
Copyright © 2026 Eilles, YuhengAlioth

开源相关声明请见 仓库根目录下的 License.md
Terms & Conditions: License.md in the root directory
"""

# 睿乐组织 开发交流群 861684859
# Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md


from typing import List

from Musicreater.builtin_plugins.to_commands import MineCommand
from .common import bottem_side_length_of_smallest_square_bottom_box, x, y, z

BDX_MOVE_KEY = {
    "x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
    "y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
    "z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
}
"""key存储了方块移动指令的数据，其中可以用key[x|y|z][0|1]来表示xyz的减或增
而key[][2+]是用来增加指定数目的"""


def bdx_move(axis: str, value: int):
    if value == 0:
        return b""
    if abs(value) == 1:
        return BDX_MOVE_KEY[axis][0 if value == -1 else 1]

    pointer = sum(
        [
            value != -1,
            value < -1 or value > 1,
            value < -128 or value > 127,
            value < -32768 or value > 32767,
        ]
    )

    return BDX_MOVE_KEY[axis][pointer] + value.to_bytes(
        2 ** (pointer - 2), "big", signed=True
    )


def form_command_block_in_BDX_bytes(
    command: str,
    particularValue: int,
    impluse: int = 0,
    condition: bool = False,
    needRedstone: bool = True,
    tickDelay: int = 0,
    customName: str = "",
    executeOnFirstTick: bool = False,
    trackOutput: bool = True,
) -> bytes:
    """
    使用指定参数生成指定的指令方块放置指令项

    Parameters
    ------------
    command: str
        指令
    particularValue: int
        方块特殊值，即朝向
        :0	下	无条件
        :1	上	无条件
        :2	z轴负方向	无条件
        :3	z轴正方向	无条件
        :4	x轴负方向	无条件
        :5	x轴正方向	无条件
        :6	下	无条件
        :7	下	无条件
        :8	下	有条件
        :9	上	有条件
        :10	z轴负方向	有条件
        :11	z轴正方向	有条件
        :12	x轴负方向	有条件
        :13	x轴正方向	有条件
        :14	下	有条件
        :14	下	有条件
        注意！此处特殊值中的条件会被下面condition参数覆写
    impluse: int (0|1|2)
        方块类型
        0脉冲 1循环 2连锁
    condition: bool
        是否有条件
    needRedstone: bool
        是否需要红石
    tickDelay: int
        执行延时
    customName: str
        悬浮字
    lastOutput: str
        命令方块的上次输出字符串，注意此处需要留空
    executeOnFirstTick: bool
        是否启用首刻执行（循环指令方块是否激活后立即执行，若为False，则从激活时起延迟后第一次执行）
    trackOutput: bool
        是否启用命令方块输出

    Returns
    ---------
    bytes
        用以生成 bdx 结构的字节码
    """
    block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False)

    for i in [
        impluse.to_bytes(4, byteorder="big", signed=False),
        bytes(command, encoding="utf-8") + b"\x00",
        bytes(customName, encoding="utf-8") + b"\x00",
        bytes("", encoding="utf-8") + b"\x00",
        tickDelay.to_bytes(4, byteorder="big", signed=True),
        executeOnFirstTick.to_bytes(1, byteorder="big"),
        trackOutput.to_bytes(1, byteorder="big"),
        condition.to_bytes(1, byteorder="big"),
        needRedstone.to_bytes(1, byteorder="big"),
    ]:
        block += i
    return block


def commands_to_BDX_bytes(
    commands_list: List[MineCommand],
    max_height: int = 64,
):
    """
    指令列表转换为用以生成 bdx 结构的字节码

    Parameters
    ------------
    commands: list[tuple[str, int]]
        指令列表，每个元素为 (指令, 延迟)
    max_height: int
        生成结构最大高度

    Returns
    ---------
    tuple[bool, bytes, int] or tuple[bool, str]
        成功与否，成功返回 (True, 未经过压缩的源, 结构占用大小)，失败返回 (False, str失败原因)
    """

    _sideLength = bottem_side_length_of_smallest_square_bottom_box(
        len(commands_list), max_height
    )
    _bytes = b""

    y_forward = True
    z_forward = True

    now_y = 0
    now_z = 0
    now_x = 0

    for command in commands_list:
        _bytes += form_command_block_in_BDX_bytes(
            command.command,
            (
                (1 if y_forward else 0)
                if (
                    ((now_y != 0) and (not y_forward))
                    or (y_forward and (now_y != (max_height - 1)))
                )
                else (
                    (3 if z_forward else 2)
                    if (
                        ((now_z != 0) and (not z_forward))
                        or (z_forward and (now_z != _sideLength - 1))
                    )
                    else 5
                )
            ),
            impluse=2,
            condition=command.conditional,
            needRedstone=False,
            tickDelay=command.delay,
            customName=command.annotation,
            executeOnFirstTick=False,
            trackOutput=True,
        )

        # (1 if y_forward else 0) if (            # 如果y+则向上，反之向下
        #     ((now_y != 0) and (not y_forward))              # 如果不是y轴上首个方块
        #     or (y_forward and (now_y != (max_height - 1)))  # 如果不是y轴上末端方块
        # ) else (                                            # 否则，即是y轴末端或首个方块
        #     (3 if z_forward else 2) if (                    # 如果z+则向z轴正方向，反之负方向
        #                 ((now_z != 0) and (not z_forward))              # 如果不是z轴上的首个方块
        #                 or (z_forward and (now_z != _sideLength - 1))   # 如果不是z轴上的末端方块
        #             ) else 5                                            # 否则，则要面向x轴正方向
        #         )

        now_y += 1 if y_forward else -1

        if ((now_y >= max_height) and y_forward) or ((now_y < 0) and (not y_forward)):
            now_y -= 1 if y_forward else -1

            y_forward = not y_forward

            now_z += 1 if z_forward else -1

            if ((now_z >= _sideLength) and z_forward) or (
                (now_z < 0) and (not z_forward)
            ):
                now_z -= 1 if z_forward else -1
                z_forward = not z_forward
                _bytes += BDX_MOVE_KEY[x][1]
                now_x += 1
            else:
                _bytes += BDX_MOVE_KEY[z][int(z_forward)]

        else:
            _bytes += BDX_MOVE_KEY[y][int(y_forward)]

    return (
        _bytes,
        [
            now_x + 1,
            max_height if now_x or now_z else now_y,
            _sideLength if now_x else now_z,
        ],
        [now_x, now_y, now_z],
    )
