# -*- coding: utf-8 -*-

# 伶伦 开发交流群 861684859


"""
伶伦转换器 命令行
Linglun Converter CLI

版权所有 © 2024 金羿 & 睿乐开发组
Copyright © 2024 EillesWan & TriM Org.

开源相关声明请见 ./License.md
Terms & Conditions: ./Lisense.md
"""

__version__ = "0.0.7"

import datetime
import os
import random

# import sys

import Musicreater
from Musicreater.constants import DEFAULT_PROGRESSBAR_STYLE
from Musicreater.plugin import ConvertConfig
from Musicreater.plugin.addonpack import (
    to_addon_pack_in_delay,
    to_addon_pack_in_repeater,
    to_addon_pack_in_score,
)

from Musicreater.plugin.mcstructfile import (
    to_mcstructure_file_in_delay,
    to_mcstructure_file_in_repeater,
    # to_mcstructure_file_in_score,
)
from Musicreater.plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score
from utils.io import logger, int_str, prt, ipt, myWords, isin, bool_str, float_str

# from Musicreater.plugin.mcstructure import commands_to_structure, commands_to_redstone_delay_structure


logger.console.print(
    "[#121110 on #F0F2F4]     ",
    style="#121110 on #F0F2F4",
    justify="center",
)

# osc.project_name = "伶伦转换器"
# osc.version = __version__


# if len(sys.argv) > 0:

#     def go_for_args(debugMode: str = "False", logfile: str = "True"):
#         global logger
#         osc.isRelease = False if debugMode.lower() in ("true", "1") else True
#         logger.printing = not osc.isRelease
#         logger.writing = True if logfile.lower() in ("true", "1") else False

#     go_for_args(*sys.argv)


# 显示大标题
logger.console.rule(
    title="[bold #AB70FF]欢迎使用伶伦独立转换器", characters="=", style="#26E2FF"
)
# MainConsole.rule(title="[bold #AB70FF]Welcome to Linglun Converter", characters="-")
logger.console.rule(
    title="[#AB70FF]版本{} | 音·创内核版本{}".format(
        __version__, Musicreater.__version__
    ),
    characters="-",
    style="#26E2FF",
)

nowYang = datetime.datetime.now()

if nowYang.month == 8 and nowYang.day == 6:
    # 诸葛八卦生日
    logger.console.print(
        "[#7DB5F0 on #121110]今天可不是催更的日子！\n诸葛亮与八卦阵{}岁生日快乐！".format(
            nowYang.year - 2008
        ),
        style="#7DB5F0 on #121110",
        justify="center",
    )
elif nowYang.month == 4 and nowYang.day == 3:
    # 金羿生日快乐
    logger.console.print(
        "[#0089F2 on #F0F2F4]今天就不要催更啦！\n金羿{}岁生日快乐！".format(
            nowYang.year - 2006
        ),
        style="#0089F2 on #F0F2F4",
        justify="center",
    )
else:
    # 显示箴言部分
    logger.console.print(
        "[#121110 on #F0F2F4]{}".format(random.choice(myWords)),
        style="#121110 on #F0F2F4",
        justify="center",
    )

# prt(f"{_('LangChd')}{_(':')}{_(currentLang)}")


def format_ipt(
    notice: str,
    fun,
    err_note: str = "输入内容有误，请重新输入。",
    *extraArg,
):
    """循环输入，以某种格式
    notice: 输入时的提示
    fun: 格式函数
    err_note: 输入不符格式时的提示
    *extraArg: 对于函数的其他参数"""
    while True:
        result = ipt(notice)
        try:
            fun_result = fun(result, *extraArg)
            break
        except ValueError:
            prt(err_note)
            continue
    return result, fun_result


# 获取midi列表
while True:
    midi_path = ipt(f"MIDI地址或所在目录地址：")
    try:
        if os.path.exists(midi_path):
            if os.path.isfile(midi_path):
                midis = (midi_path,)
            elif os.path.isdir(midi_path):
                midis = (
                    os.path.join(midi_path, i)
                    for i in os.listdir(midi_path)
                    if i.lower().endswith(".mid") or i.lower().endswith(".midi")
                )
            else:
                prt("输入内容有误，请重新输入。")
                continue
        else:
            prt("该地址不存在，或无法访问该地址，请重新输入。")
            continue
    except PermissionError:
        prt("无法访问该地址，请检查是否给予程序相关文件的访问权限。")
        continue
    break

# 获取输出地址
while True:
    out_path = ipt(f"文件生成输出地址：")
    try:
        if not os.path.exists(out_path):
            prt("该地址不存在，或无法访问该地址，请重新输入。")
            continue
    except PermissionError:
        prt("无法访问该地址，请检查是否给予程序相关文件的访问权限。")
        continue
    break


# 选择输出格式


def is_in_bdx_mcpack(sth: str):
    return isin(
        sth,
        {
            1: ("bdx", "1", "币帝查", "币帝·艾克斯", "一", "幺"),
            0: ("mcpack", "0", "唉姆西·派克", "零", "〇"),
            2: ("MCSTRUCTURE", "2", "二", "麦块结构", "MC结构", "两", "我的世界结构"),
        },
    )


def is_in_player(sth: str, in_ok: tuple):
    return isin(
        sth,
        dict(
            [
                (i, v)
                for i, v in [
                    0,
                    ("delay", "0", "延迟", "帝蕾"),
                    1,
                    ("score", "1", "计分板", "积分", "积分板", "计分", "斯阔尔"),
                    2,
                    ("repeater", "2", "中继器", "瑞皮特"),
                ]
                if i in in_ok
            ]
        ),
    )


output_file_format = format_ipt(
    "输出文件类型 (mcpack/0|bdx/1)",
    is_in_bdx_mcpack,
    "输入内容有误，请重新输入。",
)[1]

if output_file_format == 0:
    player_format = format_ipt(
        "播放器类型 (延迟/0|计分板/1|中继器/2)",
        is_in_player,
        "输入内容有误，请重新输入。",
    )[1]
elif output_file_format == 1:
    player_format = format_ipt(
        "播放器类型 (延迟/0|计分板/1)",
        lambda a: is_in_player(a, (0, 1)),
        "输入内容有误，请重新输入。",
    )[1]
else:
    player_format = format_ipt(
        "播放器类型 (延迟/0|中继器/2)",
        lambda a: is_in_player(a, (0, 2)),
        "输入内容有误，请重新输入。",
    )[1]

old_exe_enabled = not format_ipt(
    "启用新版代执行指令 (否/0|是/1)：",
    bool_str,
    "输入内容格式错误，应为 是/1/真/t/y 或 否/0/假/f/n",
)[1]


if os.path.exists("./demo_config.json"):
    import json

    prompts = json.load(open("./demo_config.json", "r", encoding="utf-8"))

    prompts = prompts[:-1]
else:
    prompts = []
    # 提示语 检测函数 错误提示语
    for args in [
        (
            "音量大小 (0,1]：",
            float_str,
        ),
        (
            "速度倍率 (0,+∞)：",
            float_str,
        ),
        (
            "自动生成进度条 (否/0|是/1)：",
            bool_str,
        ),
        (
            (
                "计分板名称：",
                str,
            )
            if player_format == 1
            else (
                "受播放玩家的选择器：",
                str,
            )
        ),
        (
            (
                "自动重置计分板 (否/0|是/1)：",
                bool_str,
            )
            if player_format == 1
            else ()
        ),
        (
            (
                "BDX作者署名：",
                str,
            )
            if output_file_format == 1
            else (
                (
                    "结构延展方向（x+|z+|x-|z-）：",
                    lambda a: isin(
                        a,
                        {
                            "z+": ["z+", "Z+"],
                            "x+": ["X+", "x+"],
                            "z-": ["Z-", "z-"],
                            "x-": ["x-", "X-"],
                        },
                    ),
                )
                if (player_format == 2 and output_file_format == 2)
                else ()
            )
        ),
        (
            (
                "结构生成最大高度 (0,+∞)：",
                int_str,
            )
            if player_format == 0
            else (
                (
                    "基础空白方块（例：concrete）：",
                    str,
                )
                if (player_format == 2 and output_file_format == 2)
                else ()
            )
        ),
    ]:
        if args:
            prompts.append(
                format_ipt(
                    *args, err_note="输入内容格式错误，应符合 {}".format(args[1])
                )[1]
            )

if prompts[2]:
    costom_pgb_enabled = format_ipt(
        "自定义进度条样式 (否/0|是/1)：",
        bool_str,
        "输入内容格式错误，应为 是/1/真/t/y 或 否/0/假/f/n",
    )[1]
    if costom_pgb_enabled:
        style = ipt("基本样式组 (回车默认)：")
        if not style:
            style = DEFAULT_PROGRESSBAR_STYLE[0]
        yet_part = ipt("未播放样式 (回车默认)：")
        if not yet_part:
            yet_part = DEFAULT_PROGRESSBAR_STYLE[1][1]
        done_part = ipt("已播放样式 (回车默认)：")
        if not done_part:
            done_part = DEFAULT_PROGRESSBAR_STYLE[1][0]

if output_file_format == 0:
    if player_format == 1:
        cvt_method = to_addon_pack_in_score
    elif player_format == 0:
        cvt_method = to_addon_pack_in_delay
    elif player_format == 2:
        cvt_method = to_addon_pack_in_repeater
elif output_file_format == 2:
    # if player_format == 1:
    #     cvt_method = to_mcstructure_file_in_score
    if player_format == 0:
        cvt_method = to_mcstructure_file_in_delay
    elif player_format == 2:
        cvt_method = to_mcstructure_file_in_repeater


for singleMidi in midis:
    prt("\n" f"正在处理 {singleMidi}")
    cvt_mid = Musicreater.MidiConvert.from_midi_file(
        singleMidi, old_exe_format=old_exe_enabled
    )
    cvt_cfg = ConvertConfig(
        out_path,
        *prompts[:2],
        progressbar=(
            ((style, (done_part, yet_part)) if costom_pgb_enabled else True)    # type: ignore
            if prompts[2]
            else False
        ),
    )

    conversion_result = (
        (cvt_method(cvt_mid, cvt_cfg, *prompts[3:]))    # type: ignore
        if output_file_format == 0
        else (
            (
                to_BDX_file_in_score(cvt_mid, cvt_cfg, *prompts[3:])
                if player_format == 1
                else to_BDX_file_in_delay(cvt_mid, cvt_cfg, *prompts[3:])
            )
            if output_file_format == 1
            else (cvt_method(cvt_mid, cvt_cfg, *prompts[3:]))   # type: ignore
        )
    )

    prt(
        f"	结构大小：{conversion_result[0]}，播放刻数：{conversion_result[1]}"
        if output_file_format == 2
        else f"	指令总长：{conversion_result[0]}，播放刻数：{conversion_result[1]}{f'''，结构大小：{conversion_result[2]}，末点坐标：{conversion_result[3]}''' if output_file_format == 1 else ''}" # type: ignore
    )

exitSth = ipt("结束。换行以退出程序。")
if exitSth == "record":
    import json

    with open("./demo_config.json", "w", encoding="utf-8") as f:
        json.dump(prompts, f)
elif exitSth == "delrec":
    os.remove("./demo_config.json")
