import re
from typing import List
from datetime import datetime
import subprocess
import sys
import argparse


def generate_signal_cmd_and_save(logcat_path: str, target_path: str):
    with open(logcat_path, "r") as logcat_file:
        contents = logcat_file.readlines()
    cmdList = generate_signal_cmd(contents)
    with open(target_path, "w") as target_file:
        target_file.write('\n'.join(cmdList))


def generate_signal_cmd(contents: List[str], inject_java: bool = False, use_log_time: bool = True) -> List[str]:
    # 03-07 19:26:46.176510  1551  1809 I MiCarPropertyService: onPropertyChange: prop=Driving#POWER_MODE(0x61407207), area=0x0, stat=0, time=633267664184, val=2
    timestamp_regex = re.compile(r'\d\d-\d\d \d\d:\d\d:\d\d.\d+')
    result = []
    tmp = []
    for item in contents:
        if "MiCarPropertyService:" in item and "onPropertyChange" in item:
            tmp.append(item)
    prev = 0
    if not inject_java:
        result.append("adb root")
    for item in tmp:
        match = timestamp_regex.search(item)
        time_str = match.group(0)
        if use_log_time:
            time = datetime.strptime(time_str, "%m-%d %H:%M:%S.%f").timestamp() * 1_000_000_000
        else:
            time = int(item.split("time=")[1].split(", val=")[0])
        if prev == 0:
            prev = time
        if time - prev > 1000000:
            delay = (time - prev) / 1e9
            result.append(f"sleep {delay:.2f}")
        prev = time
        propId = re.findall(r"\((.+?)\)", item)[0]
        area = re.findall(r"area=(.+?),", item)[0]
        val = re.findall(r"val=(.+)", item)[0]
        val = val.replace(" ", "").replace("[", "").replace("]", "")
        if inject_java:
            cmd = f"adb shell dumpsys car_service inject-vhal-event {propId} {area} {val}"
        else:
            val_list = ""
            hal_type = int(propId, 16) & 0x00ff0000
            # bool | int32 | int32_vec
            if hal_type == 0x00200000 or hal_type == 0x00400000 or hal_type == 0x00410000:
                for val_item in val.split(","):
                    val_list = val_list + " i " + val_item
            # float
            if hal_type == 0x00600000 or hal_type == 0x00610000:
                for val_item in val.split(","):
                    val_list = val_list + " f " + val_item
            # string
            if hal_type == 0x00100000:
                val_list = " s " + val
            # vhal do not support hex now
            cmd = f"adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car" \
                  f" {int(propId, 16)}{val_list} a {int(area, 16)}"
        result.append(cmd)

    return result


def main(logcat_path, output_path, execute: bool = True, inject_java: bool = False):
    print("output_path : " + str(output_path))
    # 读取 logcat 文件内容
    with open(logcat_path, 'r') as f:
        contents = f.readlines()

    # 生成命令列表
    cmd_list = generate_signal_cmd(contents, inject_java)

    # 将命令列表输出到文件或执行
    if output_path is None:
        # 如果没有输出文件，则直接执行
        execute = True
    else:
        # 如果有输出文件，则将命令列表输出到文件
        with open(output_path, 'w') as f:
            f.write('\n'.join(cmd_list))

        # if not execute:
        #     # 提示用户是否需要执行命令
        #     print(f'命令已经保存到文件 {output_path}，是否需要执行？(y/n)')
        #     answer = input().lower()
        #     if answer in ['y', 'yes']:
        #         execute = True

    # 如果需要执行命令，则执行
    if execute:
        for cmd in cmd_list:
            subprocess.run(cmd, shell=True)


if __name__ == '__main__':
    print(str(sys.argv))
    parser = argparse.ArgumentParser(description="Generate adb shell command from logcat.")
    parser.add_argument("logcat_file", help="Path to the input logcat file.")
    parser.add_argument("--output", default=None, help="Path to the output command file.")
    parser.add_argument("--save_only", action="store_true", default=None, help="Path to the output command file.")
    parser.add_argument("--inject_java_only", action="store_true", default=None, help="inject to CarService(not VHAL)")
    parser.add_argument("--exec", action="store_true", help="Execute the generated command with adb shell.")

    args = parser.parse_args()
    if args.save_only:
        args.output = "cmd_list.sh"
    main(args.logcat_file, args.output, args.exec, args.inject_java_only)
    #
    #
    # generate_signal_cmd_and_save(args.logcat_file, args.output_file)
    # if args.exec:
    #     cmd = 'cmd.exe /c' if os.name == 'nt' else 'sh -c'
    #     subprocess.run(f'{cmd} "{args.output_file}"')
