import subprocess
from datetime import datetime
from enum import Enum

from mower import __system__
from mower.utils import config
from mower.utils.csleep import MowerExit, csleep
from mower.utils.log import logger


class Emulator_Type(Enum):
    Nox = "夜神"
    MuMu12 = "MuMu12"
    Leidian9 = "雷电9"
    Waydroid = "Waydroid"
    ReDroid = "ReDroid"
    MuMuPro = "MuMuPro"
    Genymotion = "Genymotion"


def restart_emulator(stop: bool = True, start: bool = True) -> bool:
    """重启模拟器

    Args:
        stop: 停止模拟器
        start: 启动模拟器

    Returns:
        是否成功
    """
    data = config.conf.emulator
    index = data.index
    emulator_type = data.name
    emulator_folder = data.emulator_folder
    wait_time = data.wait_time
    hotkey = data.hotkey
    cmd = ""

    if emulator_type not in Emulator_Type:
        logger.warning(f"尚未支持{emulator_type}重启/自动启动")
        csleep(10)
        return False
    if emulator_type == Emulator_Type.MuMu12.value:
        mumumanager = config.device.get_service("mumumanager")

        return mumumanager.restart_emulator(stop, start)

    elif emulator_type == Emulator_Type.Nox.value:
        cmd = "Nox.exe"
        if int(index) >= 0:
            cmd += f" -clone:Nox_{index}"
        cmd += " -quit"
    elif emulator_type == Emulator_Type.Waydroid.value:
        cmd = "waydroid session stop"
    elif emulator_type == Emulator_Type.Leidian9.value:
        cmd = "ldconsole.exe quit --index "
        if int(index) >= 0:
            cmd += f"{index} "
        else:
            cmd += "0"
    elif emulator_type == Emulator_Type.ReDroid.value:
        cmd = f"docker stop {index} -t 0"
    elif emulator_type == Emulator_Type.MuMuPro.value:
        cmd = f"Contents/MacOS/mumutool close {index}"
    elif emulator_type == Emulator_Type.Genymotion.value:
        if __system__ == "windows":
            cmd = "gmtool.exe"
        elif __system__ == "darwin":
            cmd = "Contents/MacOS/gmtool"
        else:
            cmd = "./gmtool"
        cmd += f' admin stop "{index}"'

    if stop:
        logger.info(f"关闭{emulator_type}模拟器")
        exec_cmd(cmd, emulator_folder, 0)

    if start:
        csleep(3)
        if emulator_type == Emulator_Type.Nox.value:
            cmd = cmd.replace(" -quit", "")
        elif emulator_type == Emulator_Type.Waydroid.value:
            cmd = "waydroid show-full-ui"
        elif emulator_type == Emulator_Type.Leidian9.value:
            cmd = cmd.replace("quit", "launch")
        elif emulator_type == Emulator_Type.ReDroid.value:
            cmd = f"docker start {index}"
        elif emulator_type == Emulator_Type.MuMuPro.value:
            cmd = cmd.replace("close", "open")
        elif emulator_type == Emulator_Type.Genymotion.value:
            cmd = cmd.replace("stop", "start", 1)
        logger.info(f"启动{emulator_type}模拟器")
        if exec_cmd(cmd, emulator_folder, wait_time):
            if hotkey:
                hotkey = hotkey.split("+")
                import pyautogui

                pyautogui.FAILSAFE = False
                pyautogui.hotkey(*hotkey)
            return True
        return restart_emulator()
    return True


def exec_cmd(cmd, folder_path, wait_time):
    logger.debug(cmd)
    process = subprocess.Popen(
        cmd,
        shell=True,
        cwd=folder_path,
        creationflags=subprocess.CREATE_NO_WINDOW if __system__ == "windows" else 0,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True,
    )
    if config.conf.emulator.name == Emulator_Type.Genymotion.value:
        while wait_time > 0:
            try:
                csleep(0)
                logger.debug(process.communicate(timeout=1))
                return True
            except MowerExit:
                raise
            except subprocess.TimeoutExpired:
                wait_time -= 1

    else:
        start_time = datetime.now()
        while (datetime.now() - start_time).total_seconds() < wait_time:
            try:
                config.device.app_control.get_adb_while_restart_emulator()
                return True
            except MowerExit:
                raise
            except Exception as e:
                logger.debug_exception(e)
                config.device.app_control.adb_disconnect()
                csleep(1)
    return False
