"""
读取工程中所有framework并把方法属性存储到project_framework_keywords.txt
"""
import sys
import os
import re
import subprocess
from ObjectiveC import oc_util
from ObjectiveC.oc_custom import custom_core

def get_all_system_symbols(project_path, save_path):
    """
    提取系统中关键词函数
    """

    # 存储所有找到的framework关键词
    symbols = set()
    for root, dirs, files in os.walk(project_path):
        # .h文件
        for file in files:
            if file.endswith('.h'):
                file_path = os.path.join(root, file)
                with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                    content = f.read()
                    
                    # 提取属性名
                    unique_properties, property_custom_accessors = custom_core.process_property_content(content)
                    for property_name in unique_properties:
                        custom_setter = property_custom_accessors.get(property_name, (None, None))[0]
                        custom_getter = property_custom_accessors.get(property_name, (None, None))[1]
                        if custom_setter:
                            symbols.add(custom_setter)
                        if custom_getter:
                            symbols.add(custom_getter)
                    
                        # 3. 添加setter方法形式
                        capitalized = property_name[0].upper() + property_name[1:]
                        setter_name = f"set{capitalized}"
                        symbols.add(setter_name)
                        
                        # 4. 添加带下划线的实例变量名 (_propertyName)
                        ivar_name = f"_{property_name}"
                        symbols.add(ivar_name)
                        
                        # 5. 添加属性名本身
                        symbols.add(property_name)

                    # 提取实例变量
                    unique_instance_variables = custom_core.process_instance_variables_content(content)
                    symbols.update(unique_instance_variables)

                    # 使用custom_core中的枚举内容处理函数
                    all_enums = custom_core.process_enums_content(content)
                    symbols.update(all_enums)

                    # 使用custom_core中的代理内容处理函数
                    all_delegates = custom_core.process_delegates_content(content)
                    symbols.update(all_delegates)

                    # 使用custom_core中的block内容处理函数
                    all_blocks = custom_core.process_blocks_content(content)
                    symbols.update(all_blocks)
                    
                    # 使用custom_core中的常量内容处理函数
                    all_constants = custom_core.process_constants_content(content)
                    symbols.update(all_constants)

                    # 使用custom_core中的类名内容处理函数
                    class_matches = custom_core.process_class_name_content(content)
                    symbols.update(class_matches)
                    
                    # 使用custom_core中的方法内容处理函数
                    all_methods = custom_core.process_methods_content(content)
                    symbols.update(all_methods)

                    # 使用custom_core中的c语言方法内容处理函数
                    all_c_methods = custom_core.process_c_method_content(content)
                    symbols.update(all_c_methods)

                    # 其他 单个字母
                    for char in 'abcdefghijklmnopqrstuvwxyz':
                        symbols.add(char)

                    # 添加系统关键字 - 使用统一的分类定义
                    
                    # 1. 添加所有C/C++和Objective-C类型
                    # 基础C/C++类型
                    c_basic_types = {
                        # 基础类型
                        'void', 'char', 'short', 'int', 'long', 'float', 'double', 'bool',
                        # 扩展基础类型  
                        'signed', 'unsigned', 'size_t', 'ssize_t', 'wchar_t',
                        # C99标准类型
                        'int8_t', 'int16_t', 'int32_t', 'int64_t',
                        'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t',
                        'intptr_t', 'uintptr_t', 'ptrdiff_t',
                        # 其他常用类型
                        'time_t', 'clock_t', 'off_t', 'pid_t'
                    }
                    symbols.update(c_basic_types)
                    
                    # Objective-C特有类型
                    objc_types = {
                        # Objective-C基础类型
                        'BOOL', 'id', 'Class', 'SEL', 'IMP', 'Protocol'
                    }
                    symbols.update(objc_types)
                    
                    # 2. C/C++语言关键字
                    c_keywords = {
                        # 存储类说明符
                        'auto', 'static', 'extern', 'inline', 'register',
                        # 类型限定符
                        'const', 'volatile', 'restrict', 'signed', 'unsigned',
                        # 类型说明符
                        'struct', 'union', 'enum', 'typedef', 'sizeof',
                        # 控制流关键字
                        'if', 'else', 'switch', 'case', 'default', 'break', 'continue', 'return',
                        'for', 'while', 'do', 'goto',
                        # C11新增关键字
                        'alignof', 'alignas', '_Static_assert', '_Generic', '_Noreturn',
                        '_Thread_local', '_Alignas', '_Alignof'
                    }
                    symbols.update(c_keywords)
                    
                    # 4. 预处理器指令
                    preprocessor_directives = {
                        'define', 'undef', 'include', 'import',
                        'ifdef', 'ifndef', 'endif', 'if', 'elif', 'else',
                        'pragma', 'error', 'warning', 'line'
                    }
                    symbols.update(preprocessor_directives)
                    
                    # 5. 常用编程概念词汇
                    programming_concepts = {
                        'method', 'function', 'macro', 'variable', 'parameter', 'argument',
                        'class', 'object', 'instance', 'module', 'namespace', 'scope',
                        'public', 'private', 'protected', 'final', 'abstract', 'virtual',
                        'mobile', 'iPhone'
                    }
                    symbols.update(programming_concepts)

    
    # 保存关键词到文件
    with open(save_path, 'w') as f:
        # 按照字符长短排序
        for keyword in sorted(symbols, key=len, reverse=True):
            f.write(f"{keyword}\n")
    
    return symbols

def init_project(save_path, log_level=0 ,project_path=None):
    """
    初始化项目，读取所有framework中的方法和属性
    
    参数:
        save_path: 存储framework关键词的文件路径
        log_level: 日志级别 (0: 无输出, 1: 基本输出, 2: 详细输出)
    """
    if log_level > 0:
        print("开始分析项目framework...")
    
    # 获取项目路径
    if project_path is None:
        project_path = oc_util.path_mix_project
    if log_level > 0:
        print(f"项目路径：{project_path}")
    
    # 存储所有找到的framework关键词
    all_keywords = set()
    
    # 查找所有.framework文件夹
    for root, dirs, files in os.walk(project_path):
        for dir_name in dirs:
            if dir_name.endswith('.framework'):
                framework_path = os.path.join(root, dir_name)
                framework_name = dir_name[:-10]  # 去掉.framework后缀
                
                if log_level > 0:
                    print(f"分析framework: {framework_name}")
                
                # 分析framework中的二进制文件
                binary_path = os.path.join(framework_path, framework_name)
                if os.path.exists(binary_path):
                    framework_keywords = extract_framework_symbols(binary_path, framework_name, log_level)
                    all_keywords.update(framework_keywords)
                
                # 分析framework中的头文件
                headers_path = os.path.join(framework_path, 'Headers')
                if os.path.exists(headers_path):
                    header_keywords = extract_header_symbols(headers_path, log_level)
                    all_keywords.update(header_keywords)
    
    # 保存关键词到文件
    with open(save_path, 'w') as f:
        # 按照字符长短排序
        for keyword in sorted(all_keywords, key=len, reverse=True):
            f.write(f"{keyword}\n")
    
    if log_level > 0:
        print(f"总共找到 {len(all_keywords)} 个framework关键词")
        print(f"关键词已保存到: {save_path}")
    
    return all_keywords

def extract_framework_symbols(binary_path, framework_name, log_level=0):
    """
    从framework二进制文件中提取符号
    
    参数:
        binary_path: framework二进制文件路径
        framework_name: framework名称
        log_level: 日志级别
    
    返回:
        符号集合
    """
    symbols = set()
    
    try:
        # 使用nm命令提取符号
        # subprocess 注解：https://docs.python.org/3/library/subprocess.html
        result = subprocess.run(['nm', '-gU', binary_path], 
                               stdout=subprocess.PIPE, 
                               stderr=subprocess.PIPE, 
                               text=True, 
                               check=False)
        
        if result.returncode != 0:
            if log_level > 0:
                print(f"警告: 无法读取 {binary_path} 的符号 ({result.stderr.strip()})")
            return symbols
        
        output = result.stdout
        
        # 分析输出
        for line in output.split('\n'):
            if not line.strip():
                continue
            
            # 尝试提取方法和属性名
            # 典型的nm输出格式: "00001234 T _OBJC_CLASS_$_ClassName"
            parts = line.strip().split(' ')
            if len(parts) >= 3:
                symbol = parts[-1]
                
                # 处理类名
                if "_OBJC_CLASS_$_" in symbol:
                    class_name = symbol.split('_OBJC_CLASS_$_')[-1]
                    symbols.add(class_name)
                
                # 处理Objective-C方法名
                elif symbol.startswith('+[') or symbol.startswith('-['):
                    # 提取方法名: "+[ClassName methodName]" -> "methodName"
                    match = re.search(r'[\+\-]\[(.*?)\s+(.*?)\]', symbol)
                    if match:
                        class_name = match.group(1)
                        method_name = match.group(2)
                        symbols.add(class_name)
                        
                        # 处理方法名，分割为组件（比如separateWithColon:andOther:）
                        method_parts = method_name.split(':')
                        if len(method_parts) > 0:
                            symbols.add(method_parts[0])  # 主方法名
                
                # 添加其他项目特定的处理...
        
        if log_level > 1:
            print(f"从 {framework_name} 提取了 {len(symbols)} 个符号")
            
    except Exception as e:
        if log_level > 0:
            print(f"错误: 处理framework {framework_name} 时出错: {str(e)}")
    
    return symbols

def extract_header_symbols(headers_path, log_level=0):
    """
    从framework头文件中提取符号
    
    参数:
        headers_path: 头文件目录路径
        log_level: 日志级别
    
    返回:
        符号集合
    """
    symbols = set()
    
    try:
        # 遍历所有头文件
        for root, _, files in os.walk(headers_path):
            for file_name in files:
                if file_name.endswith('.h'):
                    header_path = os.path.join(root, file_name)
                    
                    with open(header_path, 'r', encoding='utf-8', errors='ignore') as f:
                        content = f.read()

                    # 提取属性名
                    unique_properties, property_custom_accessors = custom_core.process_property_content(content)
                    for property_name in unique_properties:
                        custom_setter = property_custom_accessors.get(property_name, (None, None))[0]
                        custom_getter = property_custom_accessors.get(property_name, (None, None))[1]
                        if custom_setter:
                            symbols.add(custom_setter)
                        if custom_getter:
                            symbols.add(custom_getter)
                    
                        # 3. 添加setter方法形式
                        capitalized = property_name[0].upper() + property_name[1:]
                        setter_name = f"set{capitalized}"
                        symbols.add(setter_name)
                        
                        # 4. 添加带下划线的实例变量名 (_propertyName)
                        ivar_name = f"_{property_name}"
                        symbols.add(ivar_name)
                        
                        # 5. 添加属性名本身
                        symbols.add(property_name)

                    # 提取实例变量
                    unique_instance_variables = custom_core.process_instance_variables_content(content)
                    symbols.update(unique_instance_variables)

                    # 使用custom_core中的枚举内容处理函数
                    all_enums = custom_core.process_enums_content(content)
                    symbols.update(all_enums)

                    # 使用custom_core中的代理内容处理函数
                    all_delegates = custom_core.process_delegates_content(content)
                    symbols.update(all_delegates)

                    # 使用custom_core中的block内容处理函数
                    all_blocks = custom_core.process_blocks_content(content)
                    symbols.update(all_blocks)
                    
                    # 使用custom_core中的常量内容处理函数
                    all_constants = custom_core.process_constants_content(content)
                    symbols.update(all_constants)

                    # 使用custom_core中的类名内容处理函数
                    class_matches = custom_core.process_class_name_content(content)
                    symbols.update(class_matches)
                    
                    # 使用custom_core中的方法内容处理函数
                    all_methods = custom_core.process_methods_content(content)
                    symbols.update(all_methods)

                    # 使用custom_core中的c语言方法内容处理函数
                    all_c_methods = custom_core.process_c_method_content(content)
                    symbols.update(all_c_methods)
                    
    
    except Exception as e:
        if log_level > 0:
            print(f"错误: 处理头文件时出错: {str(e)}")
    
    return symbols 

def main():

    # PYTHONPATH=/Users/apple/jumbo/xianxian/00001 
    # python3 ObjectiveC/oc_custom/custom_a_framework.py 
    # '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.2.sdk' 
    # '/Users/apple/jumbo/xianxian/00001/配置文件/ObjectiveC配置文件/system_framework_keywords_ios18.2.txt'

    # 获取命令行参数
    if len(sys.argv) < 3:
        print("用法: python custom_a_framework.py <project_path> <save_project_framework_path>")
        print("示例: python custom_a_framework.py /Users/xxx/Desktop/project /Users/xxx/Desktop/project_framework_keywords.txt")
        sys.exit(1)

    project_path = sys.argv[1]
    save_project_framework_path = sys.argv[2]
    get_all_system_symbols(project_path, save_project_framework_path)

if __name__ == "__main__":
    main()