import os
import re
import sys

from winpty import PtyProcess


class BuildAll:
    def __init__(self):
        self.current_dir = os.path.dirname(os.path.abspath(__file__))

    @staticmethod
    def __get_python_env_name_from_args():
        for arg in sys.argv[1:]:
            if arg.startswith("-python_env_name="):
                return arg.split("=")[1]
        return None

    def build_all(self):
        python_env_name = self.__get_python_env_name_from_args()
        if not python_env_name:
            python_env_name = input("请输入conda python环境的名称（例如：base）: ")
        # confirm_remove = input("是否删除输出目录及其所有内容？ (y/N) ").strip().lower()
        confirm_remove = "y"

        pyinstaller_confirm_flag = "-y" if confirm_remove == 'y' else ""

        commands = [
            (f"conda activate {python_env_name} && Pyinstaller {pyinstaller_confirm_flag} -D launcher.py",
             self.current_dir),
            (f"conda activate {python_env_name} && Pyinstaller {pyinstaller_confirm_flag} -D server.py",
             os.path.join(self.current_dir, "server")),
            ("npm run build:win", os.path.join(self.current_dir, "client"))
        ]

        for cmd, cwd in commands:
            if not self.__pre_execute_check(cmd, cwd):
                return
            self.__execute_cmd_with_pty(cmd, cwd)

    @staticmethod
    def __pre_execute_check(cmd, cwd):
        if "Pyinstaller" in cmd:
            script_name = cmd.split(" ")[-1]
            absolute_path = os.path.join(cwd, script_name)
            if not os.path.exists(absolute_path):
                print(f"Error: Python脚本 '{absolute_path}' 不存在!")
                return False
        elif cmd.startswith("npm "):
            pass
        return True

    def __execute_cmd_with_pty(self, cmd, cwd=None):
        counter_output_is_all_none: int = 0
        process = PtyProcess.spawn(["cmd", "/c", cmd], cwd=cwd)
        process.setwinsize(20, 9999)
        while process.isalive():
            try:
                output: str = process.readline()
                output = self.__remove_ansi_escape_codes(output)
                output = self.__remove_leading_newlines(output)
                if output in ["", " ", "\n", "\r\n", "\n\r"]:
                    if counter_output_is_all_none != 0:
                        continue
                    else:
                        counter_output_is_all_none += 1
                        print("\n", end='')
                        continue
                else:
                    counter_output_is_all_none = 0
                output = self.__remove_ending_newlines(output)
                print(output, end='\n')
            except EOFError:
                break  # 当伪终端关闭时跳出循环

    @staticmethod
    def __remove_ansi_escape_codes(s):
        ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
        return ansi_escape.sub('', s)

    @staticmethod
    def __remove_leading_newlines(s):
        while s.startswith(('\n\r', '\r\n', '\n', '\r')):
            for seq in ['\n\r', '\r\n', '\n', '\r']:
                if s.startswith(seq):
                    s = s[len(seq):]
        return s

    @staticmethod
    def __remove_ending_newlines(s):
        sequences = ['\n\r', '\r\n', '\n', '\r']
        while s.endswith(tuple(sequences)):
            for seq in sequences:
                if s.endswith(seq):
                    s = s[:-len(seq)]
        return s


if __name__ == "__main__":
    builder = BuildAll()
    builder.build_all()
