import re
import os
import glob
import fileinput
import xml.etree.ElementTree as ET
import pygsheets
from optparse import OptionParser
import logging

logging.basicConfig(level=logging.DEBUG)
def CDATA(text=None):
    element = ET.Element('![CDATA[')
    element.text = text
    return element

ET._original_serialize_xml = ET._serialize_xml

#CDATA特殊处理
def _serialize_xml(write, elem, qnames, namespaces,short_empty_elements, **kwargs):
    if 'name' in elem.attrib.keys() and elem.attrib['name'] in andorid_contian_cdata_keys:
        write("<{} name=\"{}\"><![CDATA[{}]]></{}>{}".format(elem.tag,elem.attrib['name'],elem.text,elem.tag,elem.tail))
    else:
        return ET._original_serialize_xml(write, elem, qnames, namespaces,short_empty_elements, **kwargs)

ET._serialize_xml = ET._serialize['xml'] = _serialize_xml



andorid_root_directory = os.path.abspath(os.path.join(os.getcwd(), os.pardir, os.pardir))
ios_root_directory = os.path.abspath(os.path.join(os.getcwd(), os.pardir, os.pardir))
ios_languages = ['ar', 'en', 'hi', 'ta', 'te', 'th', 'tr', 'zh-Hans']
#andorid_language = ['', '-ar', '-hi', '-ta', '-te', '-th', '-tr', '-zh']
# andorid_language = ['', '-ar','-hi','-bn','-es','-in','-ms','-pt','-th','-tl','-tr','-ur','-vi','-zh','-zh-TW']ru	kk	ky	tk	tg	uz
andorid_language = ['','-zh', '-ar']

#xml对CDATA解析有点问题， CDATA 数据需要在这里添加key手动处理
andorid_contian_cdata_keys = ['room_high_potential_conversion_reward','ludo_exit_game_tip','message_follow',
                              'call_send_diamond','call_end_chat_get_diamonds','call_end_chat_get_coins','call_end_chat_un_get_diamonds','call_end_chat_un_get_coins',
                              'couple_love_house_no_couple_desc','game_rules_2','game_rocket_reward_record','message_follow',
                              'room_rank_list_title','wallet_diamond_balance','wallet_coin_balance','common_cp_level_not_reach','domino_exit_game_tip','ludo_load_game_go']

def find_strings_files(root_dir,lan = "en"):
    translation_files = [f for f in glob.glob(os.path.join(root_dir, '**', lan + '.lproj', 'Localizable.strings'), recursive=True) if 'MJRefresh' not in f]
    return translation_files


def find_xml_files(root_dir = andorid_root_directory,lan = ""):
    translation_files = glob.glob(os.path.join(root_dir, '**', 'res/values'+lan, 'strings.xml'), recursive=True)
    return translation_files


def lan_of_path(path):
    parts = path.split('/')
    lan = parts[-2].strip('.lproj')
    return lan


def convert_ios_strings(value):
    placeholder_pattern = r'%\d*\$?[sdf]'
    if len(re.findall(placeholder_pattern,value)) > 0:
        value = value.replace('%s', '%@')
        value = re.sub(r'%(\d+)\$s', r'%\1$@', value)
    return value


def map_andorid_lan(lan):
    if lan == 'en':
        return ''
    elif lan == 'zh-Hans':
        return '-zh'
    else:
        return '-'+lan

def map_sheet_lan(lan):
    if lan == 'zh-Hans':
        return 'zh'
    else:
        return lan



def extract_xml_to_dic(lan = ''):
    count = 0
    translations = {}
    translation_files = find_xml_files(andorid_root_directory,lan)
    android_placeholder_pattern = r'%\d*\$?[sdf]'
    for fname in translation_files:
        print(f"Processing file: {fname}")
        tree = ET.parse(fname)
        root = tree.getroot()
        for child in root:
            key = child.attrib['name']
            value = child.text
            if len(re.findall(android_placeholder_pattern,value)) > 0:
                value = value.replace('%s', '%@')
                value = re.sub(r'%(\d+)\$s', r'%\1$@', value)

                translations[key] = value
            else:
                translations[key] = value

    return translations

def read_into_table(filelist):
    table = {}
    with fileinput.input(files=filelist) as f:
        for line in f:
            if "=" in line:
                key, value = line.split("=", 1)
                table[key.strip()[1:-1]] = value.strip()[1:-2]
    return table


def read_xml_into_table(file):
    table = {}
    with fileinput.input(files=[file]) as f:
        tree = ET.parse(file)
        root = tree.getroot()
        for child in root:
            key = child.attrib['name']
            value = child.text
            table[key] = value
    return table



def read_xml_to_table(lan = ''):
    count = 0
    translations = {}
    translation_files = find_xml_files(andorid_root_directory,lan)
    print(f"Processing read_xml_to_table lan: {lan}")
    for fname in translation_files:
        tree = ET.parse(fname)
        root = tree.getroot()
        for child in root:
            key = child.attrib['name']
            value = child.text
            # print(f'key ==> {key}')
            translations[key] = value

    return translations



def mergexml(lan = ""):
    # 创建一个 ElementTree 用于存储合并后的内容
    merged_tree = ET.ElementTree(ET.Element('resources'))
    # 遍历根目录及其子目录
    for root, dirs, files in os.walk(andorid_root_directory):
        for filename in files:
            if filename == 'strings.xml' and root.endswith("res/values"+lan):
                xml_file_path = os.path.join(root, filename)
                # print(xml_file_path)
                # 解析当前 XML 文件
                tree = ET.parse(xml_file_path)
                root_elem = tree.getroot()

                # 将当前 XML 文件的内容添加到合并后的 XML 文件中
                for elem in root_elem:
                    merged_tree.getroot().append(elem)

    # 将合并后的内容写入总的 strings.xml 文件
    outfilename =  'merged_strings'+lan +'.xml'
    outfilepath = os.path.join('MergedXml', outfilename)
    merged_tree.write(outfilepath, encoding='utf-8', xml_declaration=True)
    print(f"{lan} 合并完成 \n")



def findallxml():
    # 遍历根目录及其子目录
    for root, dirs, files in os.walk(andorid_root_directory):
        for filename in files:
            if filename == 'strings.xml' and "res/values" in root:
                # 找到 strings.xml 文件
                xml_file_path = os.path.join(root, filename)
                print(f"找到 strings.xml 文件：{xml_file_path}")
                # print(f'{filename}')


def find_all_xml_files():
    for lan  in andorid_language:
        find_xml_files(lan=lan)


def merge_all_files():
    for lan in andorid_language:
        mergexml(lan=lan)


def find_untrans_items():
    untransItems = {}
    files = find_strings_files(root_dir=ios_root_directory)
    for filename in files:
        en_tables = read_into_table(filename)
        ar_tables = read_into_table(filename.replace('en.lproj','ar.lproj'))
        result = set(en_tables.keys()) - set(ar_tables.keys())
        if len(result) > 0 :
            print(f'{filename} , untranslate keys: {result}')
            for key in result:
                print(f'{key} ==> {en_tables[key]}')
                untransItems[key] = en_tables[key]

    return untransItems


def find_all_untrans_items():
    untransItems = {}
    files = find_strings_files(root_dir=ios_root_directory)
    for filename in files:
        en_tables = read_into_table(filename)
        ar_tables = read_into_table(filename.replace('en.lproj','ar.lproj'))
        result = set(en_tables.keys()) - set(ar_tables.keys())
        if len(result) > 0 :
            print(f'{filename} , untranslate keys: {result}')
            for key in result:
                print(f'{key} ==> {en_tables[key]}')
                untransItems[key] = en_tables[key]

    return untransItems


def syn_translate_ios(transItems = {}):
    if len(transItems) > 0:
        files = find_strings_files(root_dir=ios_root_directory)
        for filename in files:
            en_tables = read_into_table(filename)
            processkeys = set(en_tables.keys()) & set(transItems.keys())
            if len(processkeys) > 0 :
                for lan in ios_languages:
                    lanfile = filename.replace('en.lproj',f'{lan}.lproj')
                    print(f'开始处理文件: {lanfile}')
                    preparekey = list(processkeys)
                    with open(lanfile, 'r', encoding='utf-8') as infile:
                        lines = infile.readlines()
                    with open(lanfile, 'w', encoding='utf-8') as outfile:
                        for line in lines:
                            if '=' in line:
                                key, value = line.strip().split("=", 1)
                                key = key.strip()[1:-1]
                                value = value.strip()[1:-2]
                                if key in transItems.keys():
                                    newvalue = convert_ios_strings(transItems[key][map_sheet_lan(lan)]).strip()
                                    if newvalue == '':
                                        newvalue = transItems[key]['en']

                                    if newvalue != value:
                                        modified_line = f'"{key}" = "{newvalue}";\n'
                                        outfile.write(modified_line)
                                        if key in preparekey:
                                            preparekey.remove(key)
                                        print(f'更新 ==>[{lan}:{key}] {value} ==> {newvalue}')
                                    else:
                                        outfile.write(line)
                                        if key in preparekey:
                                            preparekey.remove(key)
                                else:
                                    outfile.write(line)
                        for key in preparekey:
                            newvalue = convert_ios_strings(transItems[key][map_sheet_lan(lan)]).strip()
                            if newvalue == '':
                                print(f'！！添加 ==>[{lan}:{key}] 翻译为空，默认使用英文翻译')
                                newvalue = transItems[key]['en']
                            newline = f'"{key}" = "{newvalue}";\n'
                            outfile.write(newline)
                            print(f'添加 ==>[{lan}:{key}] ==> {newvalue}')
                    print(f'同步完成 \n')
            else:
                print(f'未找到英文翻译中的差异的 key \n')
    else:
        print('没有需要同步的表格数据')




def syn_translate_andorid(transItems = {}):
    if len(transItems) > 0:
        files = find_xml_files(root_dir=andorid_root_directory)
        for filename in files:
            en_tables = read_xml_into_table(filename)
            processkeys = set(en_tables.keys()) & set(transItems.keys())
            if len(processkeys) > 0 :
                for lan in andorid_language:
                    lan_key = lan.replace('-','')
                    if lan_key == '':
                        lan_key = 'en'
                    if lan=='-zh-TW':
                        lanfile = filename.replace('res/values',f'res/values-zh-rTW')
                        lan_key = 'zh-TW'
                    else :
                        lanfile = filename.replace('res/values',f'res/values{lan}')

                    # 检查目录是否存在
                    lanfile_dir = os.path.dirname(lanfile)
                    if not os.path.exists(lanfile_dir):
                        os.makedirs(lanfile_dir)  # 创建目录
                        print(f"目录 {lanfile_dir} 已创建")

                    # 检查文件是否存在
                    if not os.path.exists(lanfile):
                        with open(lanfile, 'w', encoding='utf-8') as f:
                            f.write('<?xml version="1.0" encoding="utf-8"?>\n<resources>\n</resources>')  # 可以初始化文件内容
                        print(f"文件 {lanfile} 已创建")
                    else:
                        print(f"文件 {lanfile} 已存在")
                    print(lan)
                    print(lan_key)
                    print(lanfile)
                    print(f'开始处理文件: {lanfile}')


                    preparekey = list(processkeys)
                    tree = ET.parse(lanfile)
                    root = tree.getroot()

                    for child in root:
                        key = child.attrib['name']
                        value = child.text
                        print(key)
                        print(value)
                        if key in transItems.keys():
                            newvalue = str(transItems[key][lan_key]).strip()
                            print(111)
                            print(newvalue)
                            if newvalue == '':
                                newvalue = transItems[key]['en']
                            if newvalue != value:
                                child.text = newvalue
                                print(f'更新 ==>[{lan}:{key}] {value} ==> {newvalue}')
                            if key in preparekey:
                                preparekey.remove(key)
                        else:
                            child.text = value

                    for key in preparekey:
                        newvalue = str(transItems[key][lan_key]).strip()
                        if newvalue == '':
                            print(f'！！添加 ==>[{lan}:{key}] 翻译为空，默认使用英文翻译')
                            newvalue = transItems[key]['en']
                        new_string_element = ET.Element('string')
                        new_string_element.set('name', key)
                        new_string_element.text = newvalue
                        root.append(new_string_element)
                        print(f'添加 ==>[{lan}:{key}] ==> {newvalue}')

                    ET.indent(tree, '    ')
                    tree.write(lanfile, encoding='utf-8',xml_declaration=False)
                    #write("<?xml version='1.0' encoding='%s'?>\n" % (declared_encoding,))
                    with open(lanfile,'r+') as f:
                        file_data = f.read()
                        f.seek(0, 0)
                        f.write('<?xml version="1.0" encoding="utf-8"?>\n' + file_data)
                    print(f'同步完成 \n')

    else:
        print('没有需要同步的表格数据')




class syntransition:

    def __init__(self,fileName = 'Ludo Transaltion',export = False, platform = 1,title = ''):
        self.client = pygsheets.authorize(service_file = "localizable-key.json")
        self.sheet = self.client.open(fileName)
        self.platform = platform
        # 尝试查找工作表，如果找不到，则添加一个新工作表
        try:
            self.worksheet = self.sheet.worksheet_by_title(title)

        except pygsheets.exceptions.WorksheetNotFound:
            if export:
                # 如果工作表不存在，添加一个新工作表
                template_wks = self.sheet.worksheet_by_title('template')
                self.worksheet = self.sheet.add_worksheet(title=title, src_worksheet=template_wks)
            else:
                print('工作表不存在,请检查sheet名是否正确')


    def read_sheet(self):
        tables = {}
        for row in self.worksheet.get_all_records():
            key = 'i_key' if self.platform == 2 else 'a_key'
            trans_key = row[key]
            if trans_key.strip() != '':
                tables[trans_key] = row
        return tables


def syn_translate(filename, title,platform,):
    #'消息设置页面'
    syn = syntransition(fileName=filename,title=title,platform=platform)
    translations = syn.read_sheet()
    print(translations)
    if platform == 1:
        syn_translate_andorid(translations)
    else:
        syn_translate_ios(translations)




def addParser():
    parser = OptionParser()

    parser.add_option("-f", "--fileName",
                      default="Ludo Transaltion",
                      help="表文件名称",
                      metavar="fileName")

    parser.add_option("-t", "--sheetTitle",
                      help="google sheet表格名",
                      metavar="sheetTitle")

    parser.add_option("-p", "--platform",
                      default=1,
                      help="平台（andorid: 1,ios :2 ）",
                      metavar="platform")

    (options, args) = parser.parse_args()
    print("options: %s, args: %s" % (options, args))
    return options

def startConvert(options):
    filename = options.fileName
    sheetTitle = options.sheetTitle
    platform = options.platform

    print("Start converting")

    if platform != 1:
        platform = 2
    if sheetTitle is None:
        print("google sheet表格名不能为空")
        return

    syn_translate(filename=filename,title=sheetTitle,platform=1)




if __name__ == '__main__':
    options = addParser()
    startConvert(options)
    #syn_translate(filename='Ludo Transaltion',title='ludo排行榜',platform=1)

    # 使用：表名如有空格，需要用''标识sheet表名，synxml.py -t 'ludo 排行榜'
    # synxml.py -t ludo排行榜


