import hashlib
import os
from pathlib import Path

from scripts.context import Context
from scripts.task import Task
from utils import FileUtils


def string_to_md5(text):
    # 将字符串编码为UTF-8字节
    text_bytes = text.encode('utf-8')
    # 创建MD5哈希对象并更新字节数据
    md5_hash = hashlib.md5(text_bytes)
    # 返回十六进制哈希字符串
    return md5_hash.hexdigest()


def generate_encryption_key(key: str, s_len: int = -1, target_package_name: str = "") -> str:
    # if game_editor == "Cocos":
    #     return key
    handle_key = target_package_name + key + target_package_name
    processed_key = string_to_md5(handle_key)
    while processed_key[0].isdigit():
        processed_key = processed_key[1:]  # 移除首字符

    # 计算目标长度
    if s_len > 0:
        target_length = s_len
    else:
        target_length = len(key)

    # 取前N位（根据原始key长度），不足则全部保留
    # 如果处理后的key为空（极小概率），则返回空字符串
    return processed_key[:target_length] if processed_key else ""


layout_path = "LauncherCode/res/layout".replace("/", os.sep)
drawable_xxhdpi_path = "LauncherCode/res/drawable-xxhdpi".replace("/", os.sep)
drawable_path = "LauncherCode/res/drawable".replace("/", os.sep)
code_path = "LauncherCode/src".replace("/", os.sep)

android_manifest_path = "lawnchair/AndroidManifest.xml".replace("/", os.sep)
xml_path = "lawnchair/res/xml".replace("/", os.sep)
launcher_code_path = "lawnchair/src".replace("/", os.sep)
src_code_path = "src".replace("/", os.sep)
launchercode = "launchercode"


class ProjectProguard(Task):
    def __init__(self, context: Context):
        super().__init__(context)
        self.context.proguard_dict = {
            launchercode: generate_encryption_key(launchercode, target_package_name=self.context.package_name)}

    def add_proguard_key(self, key: str) -> str:
        value = self.context.proguard_dict.get(key)
        if value:
            return value
        value = generate_encryption_key(key, target_package_name=self.context.package_name)
        self.context.proguard_dict[key] = value
        return value

    def rename_files_in_dir(self, dir_path: str):
        for root, dirs, files in os.walk(dir_path):
            for file in files:
                file_path = os.path.join(root, file)
                name = Path(file).stem
                add_proguard_key = self.add_proguard_key(name)
                FileUtils.move(file_path,
                               os.path.join(root, file.replace(name, add_proguard_key))
                               .replace(launchercode, self.context.proguard_dict.get(launchercode)),
                               overwrite=True)

    def update(self, file_path: str):
        text = open(file_path, "r", encoding="UTF-8").read()
        for key, value in self.context.proguard_dict.items():
            text = text.replace(key, value)
            pass
        open(file_path, "w", encoding="UTF-8").write(text)

    def update_proguard(self, dir_path: str):
        if os.path.isdir(dir_path):
            for root, dirs, files in os.walk(dir_path):
                for file in files:
                    if file.endswith(".xml") or file.endswith(".java") or file.endswith(".kt"):
                        file_path = os.path.join(root, file)
                        self.update(file_path)
        else:
            self.update(dir_path)
        pass

    def execute(self):
        self.rename_files_in_dir(os.path.join(self.context.temp_project_path, layout_path))
        self.rename_files_in_dir(os.path.join(self.context.temp_project_path, drawable_xxhdpi_path))
        self.rename_files_in_dir(os.path.join(self.context.temp_project_path, drawable_path))
        self.rename_files_in_dir(os.path.join(self.context.temp_project_path, code_path))

        self.context.proguard_dict = {
            k: v for k, v in sorted(
                self.context.proguard_dict.items(),
                key=lambda item: len(item[0]),
                reverse=True
            )
        }
        self.update_proguard(os.path.join(self.context.temp_project_path, layout_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, drawable_xxhdpi_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, drawable_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, code_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, android_manifest_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, xml_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, launcher_code_path))
        self.update_proguard(os.path.join(self.context.temp_project_path, src_code_path))
        pass
