"""音创系列的转换功能"""
# 诸葛亮与八卦阵帮忙修改语法 日期：---2022年1月19日
# 统计：致命（三级）错误：0个；警告（二级）错误：2个；语法（一级）错误：192个


from nmcsup.log import log

import amulet
import amulet_nbt
from amulet.api.block import Block
from amulet.api.block_entity import BlockEntity
from amulet.utils.world_utils import block_coords_to_chunk_coords
from amulet_nbt import TAG_String, TAG_Compound, TAG_Byte


# 输入一个列表 [ [str, float ], [], ... ] 音符str 值为持续时间float
def note2list(Notes: list) -> list:
    from nmcsup.const import notes

    def change(base):
        enwo = {
            'a': 'A',
            'b': 'B',
            'c': 'C',
            'd': "D",
            "e": "E",
            'f': 'F',
            'g': "G"
        }
        nuwo = {
            '6': 'A',
            '7': 'B',
            '1': 'C',
            '2': "D",
            "3": "E",
            '4': 'F',
            '5': "G"
        }
        for k, v in enwo.items():
            if k in base:
                base = base.replace(k, v)
        for k, v in nuwo.items():
            if k in base:
                base = base.replace(k, v)
        return base

    res = []
    log("	===	音符列表=>音调列表")
    for i in Notes:
        s2 = change(i[0])
        log('	===	正在操作音符' + i[0] + '->' + s2)
        if s2 in notes.keys():
            log("	===	找到此音符，加入：" + str(notes[s2][0]))
            res.append([notes[s2][0], float(i[1])])
        else:
            log('	===	' + s2 + '不在音符表内，此处自动替换为 休止符0 ')
            res.append(['0', float(i[1])])
    log('	===	最终反回' + str(res))
    return res


def mcnote2freq(Notes):
    from nmcsup.const import notes
    mcnback = {}
    for i, j in notes.items():
        mcnback[j[0]] = i
    res = []
    log("	===	我的世界音调表=>频率列表")
    for i in Notes:
        log('	===	正在操作音符' + i[0] + '->' + mcnback[i[0]])
        res.append([notes[mcnback[i[0]]][1], float(i[1])])
    log('	===	最终反回' + str(res))
    return res


# MP3文件转midi文件
def Mp32Mid(mp3File, midFile):
    from piano_transcription_inference import PianoTranscription, sample_rate, load_audio
    # 加载
    (audio, _) = load_audio(mp3File, sr=sample_rate)  # , mono=True
    # 实例化并转换
    PianoTranscription(device="cpu").transcribe(audio, midFile)


# 传入一个音符列表转为指令列表
def Note2Cmd(Notes: list, ScoreboardName: str, Instrument: str, PlayerSelect: str = '',
             isProsess: bool = False) -> list:
    commands = []
    a = 0.0
    length = len(Notes)
    j = 1
    for i in range(len(Notes)):
        commands.append("execute @a" + PlayerSelect + " ~ ~ ~ execute @s[scores={" + ScoreboardName + "=" + str(
            int((a + 2) * 5 + int(Notes[i][1] * 5))) + "}] ~ ~ ~ playsound " + Instrument + " @s ~ ~ ~ 1000 " + str(
            Notes[i][0]) + " 1000\n")
        a += Notes[i][1]
        if isProsess:
            commands.append("execute @a" + PlayerSelect + " ~ ~ ~ execute @s[scores={" + ScoreboardName + "=" + str(
                int((a + 2) * 5 + int(Notes[i][1] * 5))) + "}] ~ ~ ~ title @s actionbar §e▶  播放中：  §a" + str(
                j) + "/" + str(length) + "  ||  " + str(int(j / length * 1000) / 10) + "\n")
            j += 1
    commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队  : W-YI（金羿）\n")
    return commands


# def newDataStructureCounterChange():


# 简单载入方块
# level.set_version_block(posx,posy,posz,"minecraft:overworld",("bedrock", (1, 16, 20)),Block(namespace, name))


# 转入指令列表与位置信息转至世界
def Cmd2World(cmd: list, world: str, dire: list):
    """将指令以命令链的形式载入世界\n
    cmd指令列表位为一个序列，中包含指令字符串\n
    world为地图所在位置，需要指向文件夹，dire为指令方块生成之位置"""
    level = amulet.load_level(world)
    cdl = []
    for i in cmd:
        # e = True
        try:
            if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''):
                cdl.append(i[:i.index('#')])
            # e = False
        except:
            cdl.append(i)
        # finally:
        #     if e is True:
        #         cdl.append(i)
    i = 0
    # 第一个是特殊
    universal_block = Block('universal_minecraft', 'command_block',
                            {'conditional': TAG_String("false"), 'facing': TAG_String('up'),
                             'mode': TAG_String("repeating")})
    cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
    chunk = level.get_chunk(cx, cz, "minecraft:overworld")
    offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
    universal_block_entity = BlockEntity('universal_minecraft', 'command_block', dire[0], dire[1], dire[2],
                                         amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound(
                                             {'auto': TAG_Byte(0), 'Command': TAG_String(cdl.pop(0))})})))
    chunk.blocks[offset_x, dire[1], offset_z] = level.block_palette.get_add_block(universal_block)
    chunk.block_entities[(dire[0], dire[1], dire[2])] = universal_block_entity
    chunk.changed = True
    # 集体上移
    dire[1] += 1
    # 真正开始
    down = False
    for j in cdl:
        if dire[1] + i >= 255:
            dire[0] += 1
            i = 0
            down = not down
        # 定义此方块
        if dire[1] + i == 254:
            universal_block = Block('universal_minecraft', 'command_block',
                                    {'conditional': TAG_String("false"), 'facing': TAG_String('east'),
                                     'mode': TAG_String("chain")})
        else:
            if down:
                universal_block = Block('universal_minecraft', 'command_block',
                                        {'conditional': TAG_String("false"), 'facing': TAG_String('down'),
                                         'mode': TAG_String("chain")})
            else:
                universal_block = Block('universal_minecraft', 'command_block',
                                        {'conditional': TAG_String("false"), 'facing': TAG_String('up'),
                                         'mode': TAG_String("chain")})
        cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
        # 获取区块
        chunk = level.get_chunk(cx, cz, "minecraft:overworld")
        offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
        if down:
            # 定义方块实体
            universal_block_entity = BlockEntity('universal_minecraft', 'command_block', dire[0], 254 - i, dire[2],
                                                 amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound(
                                                     {'auto': TAG_Byte(1), 'Command': TAG_String(j)})})))

            # 将方块加入世界
            chunk.blocks[offset_x, 254 - i, offset_z] = level.block_palette.get_add_block(universal_block)
            chunk.block_entities[(dire[0], 254 - i, dire[2])] = universal_block_entity
        else:
            # 定义方块实体
            universal_block_entity = BlockEntity('universal_minecraft', 'command_block', dire[0], dire[1] + i, dire[2],
                                                 amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound(
                                                     {'auto': TAG_Byte(1), 'Command': TAG_String(j)})})))

            # 将方块加入世界
            chunk.blocks[offset_x, dire[1] + i, offset_z] = level.block_palette.get_add_block(universal_block)
            chunk.block_entities[(dire[0], dire[1] + i, dire[2])] = universal_block_entity
        # 设置为已更新区块
        chunk.changed = True
        i += 1
    del i, cdl
    # 保存世界并退出
    level.save()
    level.close()


# 音符转成方块再加载到世界里头
def Blocks2World(world: str, dire: list, Datas: list):
    from nmcsup.const import Blocks
    level = amulet.load_level(world)
    i = 0

    def setblock(block: str, pos: list):
        """pos : list[int,int,int]"""
        cx, cz = block_coords_to_chunk_coords(pos[0], pos[2])
        chunk = level.get_chunk(cx, cz, "minecraft:overworld")
        offset_x, offset_z = pos[0] - 16 * cx, pos[2] - 16 * cz
        chunk.blocks[offset_x, pos[1], offset_z] = level.block_palette.get_add_block(Block("minecraft", block))
        chunk.changed = True

    for j in Datas:
        if dire[1] + 1 >= 255:
            i = 0
            dire[0] += 1
        setblock(Blocks[j[0]], [dire[0], dire[1] + i, dire[2]])
        i = int(i + j[1] + 0.5)  # 四舍五入
    level.save()
    level.close()


# 传入音符列表制作播放器指令
def Notes2Player(Note, dire: list, CmdData: dict):
    """传入音符列表、坐标、指令数据，生成播放器指令"""
    Notes = {}
    for i in Note:
        Notes[i[0]] = ''
    Notes = list(Notes.keys())
    from nmcsup.const import Blocks
    Cmds = []
    for j in Notes:
        Cmds.append('execute @e[x=' + str(dire[0]) + ',y=' + str(dire[1]) + ',z=' + str(dire[2]) + ',dy=' + str(
            255 - dire[1]) + ',name=' + CmdData['Ent'] + '] ~ ~ ~ detect ~ ~ ~ ' + Blocks[j] + ' 0 execute @a ' +
                    CmdData['Pls'] + ' ~ ~ ~ playsound ' + CmdData['Ins'] + ' @s ~ ~ ~ 1000 ' + str(j) + ' 1000\n')
    Cmds += ['#本函数由 金羿 音·创 生成\n', 'execute @e[y=' + str(dire[1]) + ',dy=' + str(255 - dire[1]) + ',name=' + CmdData[
        'Ent'] + '] ~ ~ ~ tp ~ ~1 ~\n',
             'execute @e[y=255,dy=100,name=' + CmdData['Ent'] + '] ~ ~ ~ tp ~1 ' + str(dire[1]) + ' ~\n',
             '#音·创 开发交流群 861684859']
    return Cmds


# 传入音符列表生成方块至世界
def Datas2BlkWorld(NoteData, world: str, dire: list):
    for i in range(len(NoteData)):
        Blocks2World(world, [dire[0], dire[1], dire[2] + i], NoteData[i])
