"""
修改工程名
"""
import os, json, random, re, plistlib
from ObjectiveC import oc_util

def replace_project_name_in_all_files(old_name, new_name):
    """
    在所有源代码文件中替换工程名
    """
    # print("开始替换所有文件中的工程名...")
    source_extensions = ['.h', '.m', '.mm', '.c', '.cpp', '.swift', '.xcworkspacedata', '.pbxproj', '.md']
    
    for root, _, files in os.walk(oc_util.path_mix_project, topdown=True):
        for name in files:
            ext = os.path.splitext(name)[1]
            if ext in source_extensions:
                file_path = os.path.join(root, name)
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        file_content = f.read()
                    
                    # 检查文件是否包含旧工程名
                    if old_name in file_content:
                        # 替换 Objective-C 字符串常量
                        file_content = replace_objc_string_literals(file_content, old_name, new_name)
                        # 替换 Xcode 项目引用路径 location = "group:XXGPlayKit.xcodeproj">
                        file_content = replace_xcode_project_reference(file_content, old_name, new_name)
                        # 替换头文件导入 #import <XXGPlayKit/XXGPlayKit.h>
                        file_content = replace_import_statements(file_content, old_name, new_name)
                        
                        # 特别处理 xcworkspacedata 文件中的引用
                        if name.endswith('.xcworkspacedata'):
                            file_content = replace_workspace_references(file_content, old_name, new_name)
                        
                        with open(file_path, 'w', encoding='utf-8') as f:
                            f.write(file_content)
                        # print(f"已替换文件: {file_path}")
                except Exception as e:
                    print(f"处理文件 {file_path} 时出错: {e}")
    
    # 特别处理上层目录中的 xcworkspace 文件
    parent_dir = os.path.dirname(oc_util.path_mix_project)
    for root, _, files in os.walk(parent_dir, topdown=True):
        for name in files:
            if name.endswith('.xcworkspacedata'):
                file_path = os.path.join(root, name)
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        file_content = f.read()
                    
                    if old_name in file_content:
                        file_content = replace_workspace_references(file_content, old_name, new_name)
                        
                        with open(file_path, 'w', encoding='utf-8') as f:
                            f.write(file_content)
                        print(f"已更新工作空间引用: {file_path}")
                except Exception as e:
                    print(f"处理工作空间文件 {file_path} 时出错: {e}")
    
    print("所有文件中的工程名替换完成")

def replace_workspace_references(file_content, old_name, new_name):
    """
    替换 xcworkspace 文件中的项目引用
    """
    # 处理 location = "group:bbb/ThirdMiddlewares.xcodeproj" 格式
    pattern = r'(location\s*=\s*"[^"]*/)' + re.escape(old_name) + r'(\.xcodeproj")'
    replacement = r'\1' + new_name + r'\2'
    file_content = re.sub(pattern, replacement, file_content)
    
    # 处理 location = "group:ThirdMiddlewares.xcodeproj" 格式
    pattern = r'(location\s*=\s*"[^/]*:)' + re.escape(old_name) + r'(\.xcodeproj")'
    replacement = r'\1' + new_name + r'\2'
    file_content = re.sub(pattern, replacement, file_content)
    
    return file_content

def replace_xcode_project_reference(file_content, old_name, new_name):
    """
    替换 Xcode 项目引用路径
    例如：
    - location = "group:XXGPlayKit.xcodeproj"> -> location = "group:NewName.xcodeproj">
    - location = "group:XXGThirdMiddlewares/old.xcodeproj"> -> location = "group:XXGThirdMiddlewares/new.xcodeproj">
    """
    # 处理直接引用的情况 (group:XXGPlayKit.xcodeproj)
    pattern = r'(location\s*=\s*"group:)' + re.escape(old_name) + r'(\.xcodeproj">)'
    replacement = r'\1' + new_name + r'\2'
    file_content = re.sub(pattern, replacement, file_content)
    
    # 处理子目录中的引用 (group:XXGThirdMiddlewares/old.xcodeproj)
    pattern = r'(location\s*=\s*"group:[^"]*/)' + re.escape(old_name) + r'(\.xcodeproj">)'
    replacement = r'\1' + new_name + r'\2'
    file_content = re.sub(pattern, replacement, file_content)
    
    return file_content

def replace_import_statements(file_content, old_name, new_name):
    """
    替换头文件导入语句，处理各种情况
    """
    # 替换 #import <XXGPlayKitOS/XXGPlayKitOS.h> 格式
    pattern = r'(#import\s*<|<)(' + re.escape(old_name) + r')(/)([^/>]*)(' + re.escape(old_name) + r')(\.h>)'
    replacement = r'\1' + new_name + r'\3\4' + new_name + r'\6'
    file_content = re.sub(pattern, replacement, file_content)
    
    # 替换 #import <XXGPlayKitOS/任何文件.h> 格式
    pattern = r'(#import\s*<|<)(' + re.escape(old_name) + r')(/)([^>]*>)'
    replacement = r'\1' + new_name + r'\3\4'
    file_content = re.sub(pattern, replacement, file_content)
    
    return file_content

def modify_project_name(u_new_name=None):
    old_name = oc_util.name_current_project
    new_name = random_one_project_name() if u_new_name==None else u_new_name
    modify_dir_name(old_name, new_name)
    oc_util.name_current_project = new_name
    modify_file_content(old_name, new_name)
    modify_mac_login_name(old_name, new_name)
    # 添加对所有文件的处理
    replace_project_name_in_all_files(old_name, new_name)

def modify_dir_name(old_name, new_name):
    contains_dir = [old_name, old_name+'.xcodeproj', old_name+'.bundle']
    for root, dirs, _ in os.walk(oc_util.path_mix_project, topdown=True):
        dirs[:] = [d for d in dirs if d in contains_dir]
        for name in dirs:
            dir_path = os.path.join(root, name)
            name = name.replace(old_name, new_name, 1)
            new_path = os.path.join(root, name)
            os.rename(dir_path, new_path)
def replace_objc_string_literals(file_content, old_name, new_name):
    """
    替换 Objective-C 字符串常量中的工程名
    例如：@"XXGPlayKit" -> @"NewName"
    """
    pattern = r'@"' + re.escape(old_name) + r'"'
    replacement = '@"' + new_name + '"'
    return re.sub(pattern, replacement, file_content)

def modify_file_content(old_name, new_name):
    contains_file = ['project.pbxproj', old_name+'.xcscheme', old_name+'.h', old_name+'.m']
    for root, _, files in os.walk(oc_util.path_mix_project, topdown=True):
        files[:] = [f for f in files if f in contains_file]
        for name in files:
            file_path = os.path.join(root, name)
            with open(file_path, 'r') as f:
                file_content = f.read()
                file_content = replace_file_content(file_content, old_name, new_name)

                if name == (old_name+'.h') or name == (old_name+'.m'):
                    file_content = replace_file_content(file_content, old_name+'VersionNumber;', new_name+'VersionNumber;')
                    file_content = replace_file_content(file_content, old_name+'VersionString', new_name+'VersionString')
                    file_content = replace_file_content(file_content, 'path ='+old_name+'/', 'path ='+new_name+'/')
                    # 使用专门的函数处理 Objective-C 字符串常量
                    file_content = replace_objc_string_literals(file_content, old_name, new_name)
            with open(file_path, 'w') as f:
                f.write(file_content)
            name = name.replace(old_name, new_name)
            new_path = os.path.join(root, name)
            os.rename(file_path, new_path)
def modify_mac_login_name(old_text, new_text):
    ''' 修改mac登录用户名 '''
    op_path = ''
    for root, dirs, _ in os.walk(oc_util.path_mix_project, topdown=True):
        dirs[:] = [d for d in dirs if d==(oc_util.name_current_project+'.xcodeproj')]
        for name in dirs:
            op_path = os.path.join(root, name)
    for root, dirs, files in os.walk(op_path, topdown=True):
        for name in dirs:
            name_tuple = os.path.splitext(name)
            if name_tuple[1] == '.xcuserdatad':
                old_path = os.path.join(root, name)
                new_name = random.choice(oc_util.list_random_words).lower()
                name = name.replace(name_tuple[0], new_name)
                new_path = os.path.join(root, name)
                os.rename(old_path, new_path)
    for root, dirs, files in os.walk(op_path, topdown=True):
        for name in files:
            if name == 'xcschememanagement.plist':
                file_path = os.path.join(root, name)
                with open(file_path, 'rb') as f:
                    file_content = plistlib.load(f)
                    name_dict = file_content['SchemeUserState']
                    old_key = '%s.xcscheme_^#shared#^_'%old_text
                    new_key = '%s.xcscheme_^#shared#^_'%new_text
                    name_dict[new_key] = name_dict.pop(old_key)
                    file_content['SchemeUserState'] = name_dict
                with open(file_path, 'wb') as f:
                    plistlib.dump(file_content, f)

def replace_file_content(file_content, old_text, new_text):
    p1 = re.compile(r'[^a-zA-Z0-9_]%s[^a-zA-Z0-9_]'%old_text, re.S)
    a_list = p1.findall(file_content)
    new_file_content = file_content
    for a in a_list:
        newA = a.replace(old_text, new_text)
        new_file_content = new_file_content.replace(a, newA)
    # 开头 
    if new_file_content.startswith(old_text):
        if (new_file_content[len(old_text)].encode('UTF-8').isalpha() == False) and (new_file_content[len(old_text)].isdigit() == False):
            name = new_file_content[:(len(old_text)+1)]
            newName = name.replace(old_text, new_text)
            new_file_content = new_file_content.replace(name, newName, 1)
    # 结尾
    if new_file_content.endswith(old_text):
        if (new_file_content[-1-len(old_text)].encode('UTF-8').isalpha() == False) and (new_file_content[-1-len(old_text)].isdigit() == False):
            name = new_file_content[(len(new_file_content)-len(old_text)-1):]
            newName = name.replace(old_text, new_text)
            compile_regex = re.compile(r'%s$'%name)
            new_file_content = compile_regex.sub(newName, new_file_content)
    return new_file_content
def random_one_project_name():
    ''' 随机一个工程名 '''
    name = ''
    for _ in range(random.randint(1, 1)):
        name = name + random.choice(oc_util.list_random_words).capitalize()
        name = name + random.choice(oc_util.list_random_words).capitalize()
    return name