import os
import re

from dev_tools.slpp import slpp
from module.base.utils import location2node
from module.os.map_data import DIC_OS_MAP
from module.logger import logger  # Change folder automatically


def load_lua(folder, file, prefix):
    with open(os.path.join(folder, file), 'r', encoding='utf-8') as f:
        text = f.read()
    print(f'Loading {file}')
    result = slpp.decode(text[prefix:])
    print(f'{len(result.keys())} items loaded')
    return result


def load_lua_by_function(folder, file):
    with open(os.path.join(folder, file), 'r', encoding='utf-8') as f:
        text = f.read()
    print(f'Loading {file}')
    matched = re.findall('function \(\)(.*?)end\(\)', text, re.S)
    result = {}
    for func in matched:
        add = slpp.decode('{' + func + '}')
        result.update(add)

    print(f'{len(result.keys())} items loaded')
    return result


class OSChapter:
    def __init__(self, folder):
        self.folder = folder
        self.chapter = {}
        folder = os.path.join(self.folder, 'zh-CN', 'sharecfg')
        data = load_lua(folder, 'world_chapter_random.lua', prefix=40)
        for index, chapter in data.items():
            if not isinstance(index, int) or index >= 200:
                continue
            self.chapter[index] = {'cn': chapter['name'], 'hazard_level': chapter['hazard_level']}

        for index, name in self.extract_chapter_name('en-US').items():
            self.chapter[index]['en'] = name
        for index, name in self.extract_chapter_name('ja-JP').items():
            self.chapter[index]['jp'] = name
        for index, shape in self.extract_map_size().items():
            self.chapter[index]['shape'] = shape
        # hazard_level
        new = {}
        for index, chapter in self.chapter.items():
            new[index] = {
                # The structure of world_chapter_template.lua has changed, so load the old map data
                'shape': chapter.get('shape', DIC_OS_MAP[index]['shape']),
                'hazard_level': chapter['hazard_level'],
                'cn': chapter['cn'],
                'en': chapter['en'],
                'jp': chapter['jp']
            }
        self.chapter = new

        for index, data in self.extract_map_position().items():
            self.chapter[index].update(data)

    def extract_chapter_name(self, server):
        folder = os.path.join(self.folder, server, 'sharecfg')
        data = load_lua(folder, 'world_chapter_random.lua', prefix=40)
        out = {}
        for index, chapter in data.items():
            if not isinstance(index, int) or index >= 200:
                continue
            name = chapter['name']
            name = name.replace('é', 'e')  # OCR can't recognise letter "é"
            out[index] = name

        return out

    def extract_map_size(self, server='zh-CN'):
        folder = os.path.join(self.folder, server, 'sharecfg')
        data = load_lua_by_function(folder, 'world_chapter_template.lua')
        out = {}
        for full_index, chapter in data.items():
            if not full_index // 1000000 == 1 or not chapter['map_sight']:
                continue
            index = (full_index % 1000000) // 1000
            if index < 10:
                index -= 1
            shape = self.parse_map_data(chapter['grids'])
            out[index] = location2node(shape)

        return out

    def parse_map_data(self, grids):
        y = [grid[0] for grid in grids.values()]
        x = [grid[1] for grid in grids.values()]
        return (max(x) - min(x), max(y) - min(y))

    def extract_map_position(self, server='zh-CN'):
        folder = os.path.join(self.folder, server, 'sharecfg')
        data = load_lua(folder, 'world_chapter_colormask.lua', prefix=43)
        out = {}
        for chapter in data.values():
            if 'serial_number' not in chapter:
                continue
            else:
                index = int(chapter['serial_number'])
                if index < 10:
                    index -= 1
                out[index] = {}

            area = chapter['area_pos']
            out[index]['area_pos'] = (area[0], area[1])
            offset = chapter['offset_pos']
            out[index]['offset_pos'] = (offset[0], offset[1])
            out[index]['region'] = chapter['regions']

        return out

    def encode(self):
        lines = []
        lines.append('# This file is generated by dev_tools.os_extract')
        lines.append("# Don't modified it manually.")
        lines.append('')
        lines.append('DIC_OS_MAP = {')
        for index, chapter in self.chapter.items():
            lines.append(f'    {index}: {str(chapter)},')
        lines.append('}')
        return lines

    def write(self, file):
        print(f'writing {file}')
        with open(file, 'w', encoding='utf-8') as f:
            for text in self.encode():
                f.write(text + '\n')


"""
This an auto-tool to extract map data for operation siren.

Git clone https://github.com/Dimbreath/AzurLaneData, to get the decrypted scripts.
Arguments:
    FILE:  Path to repository, such as 'xxx/AzurLaneData'
    SAVE:  File to save, 'module/os/map_data.py'
"""
FOLDER = ''
SAVE = 'module/os/map_data.py'

cha = OSChapter(FOLDER)
cha.write(SAVE)
