#!/usr/bin/env python3
# Copyright © 2019, 2022 Intel Corporation
# SPDX-License-Identifier: MIT

from __future__ import annotations
from collections import OrderedDict
import copy
import io
import pathlib
import os.path
import re
import xml.etree.ElementTree as et
import typing

if typing.TYPE_CHECKING:
    class Args(typing.Protocol):

        files: typing.List[pathlib.Path]
        validate: bool
        quiet: bool


def get_filename(element: et.Element) -> str:
    return element.attrib['filename']

def get_name(element: et.Element) -> str:
    return element.attrib['name']

def get_value(element: et.Element) -> int:
    return int(element.attrib['value'], 0)

def get_start(element: et.Element) -> int:
    return int(element.attrib['start'], 0)


BASE_TYPES = {
    'address',
    'offset',
    'int',
    'uint',
    'bool',
    'float',
    'mbz',
    'mbo',
}

FIXED_PATTERN = re.compile(r"(s|u)(\d+)\.(\d+)")

def is_base_type(name: str) -> bool:
    return name in BASE_TYPES or FIXED_PATTERN.match(name) is not None

def add_struct_refs(items: typing.OrderedDict[str, bool], node: et.Element) -> None:
    if node.tag == 'field':
        if 'type' in node.attrib and not is_base_type(node.attrib['type']):
            t = node.attrib['type']
            items[t] = True
        return
    if node.tag not in {'struct', 'group'}:
        return
    for c in node:
        add_struct_refs(items, c)


class Struct(object):
    def __init__(self, xml: et.Element):
        self.xml = xml
        self.name = xml.attrib['name']
        self.deps: typing.OrderedDict[str, Struct] = OrderedDict()

    def find_deps(self, struct_dict, enum_dict) -> None:
        deps: typing.OrderedDict[str, bool] = OrderedDict()
        add_struct_refs(deps, self.xml)
        for d in deps.keys():
            if d in struct_dict:
                self.deps[d] = struct_dict[d]

    def add_xml(self, items: typing.OrderedDict[str, et.Element]) -> None:
        for d in self.deps.values():
            d.add_xml(items)
        items[self.name] = self.xml


# ordering of the various tag attributes
GENXML_DESC = {
    'genxml'      : [ 'name', 'gen', ],
    'import'      : [ 'name', ],
    'exclude'     : [ 'name', ],
    'enum'        : [ 'name', 'value', 'prefix', ],
    'struct'      : [ 'name', 'length', ],
    'field'       : [ 'name', 'start', 'end', 'type', 'default', 'prefix', 'nonzero' ],
    'instruction' : [ 'name', 'bias', 'length', 'engine', ],
    'value'       : [ 'name', 'value', 'dont_use', ],
    'group'       : [ 'count', 'start', 'size', ],
    'register'    : [ 'name', 'length', 'num', ],
}


def node_validator(old: et.Element, new: et.Element) -> bool:
    """Compare to ElementTree Element nodes.
    
    There is no builtin equality method, so calling `et.Element == et.Element` is
    equivalent to calling `et.Element is et.Element`. We instead want to compare
    that the contents are the same, including the order of children and attributes
    """
    return (
        # Check that the attributes are the same
        old.tag == new.tag and
        old.text == new.text and
        (old.tail or "").strip() == (new.tail or "").strip() and
        list(old.attrib.items()) == list(new.attrib.items()) and
        len(old) == len(new) and

        # check that there are no unexpected attributes
        set(new.attrib).issubset(GENXML_DESC[new.tag]) and

        # check that the attributes are sorted
        list(new.attrib) == list(old.attrib) and
        all(node_validator(f, s) for f, s in zip(old, new))
    )


def process_attribs(elem: et.Element) -> None:
    valid = GENXML_DESC[elem.tag]
    # sort and prune attributes
    elem.attrib = OrderedDict(sorted(((k, v) for k, v in elem.attrib.items() if k in valid),
                                     key=lambda x: valid.index(x[0])))
    for e in elem:
        process_attribs(e)


def sort_xml(xml: et.ElementTree) -> None:
    genxml = xml.getroot()

    imports = xml.findall('import')

    enums = sorted(xml.findall('enum'), key=get_name)
    enum_dict: typing.Dict[str, et.Element] = {}
    for e in enums:
        e[:] = sorted(e, key=get_value)
        enum_dict[e.attrib['name']] = e

    # Structs are a bit annoying because they can refer to each other. We sort
    # them alphabetically and then build a graph of dependencies. Finally we go
    # through the alphabetically sorted list and print out dependencies first.
    structs = sorted(xml.findall('./struct'), key=get_name)
    wrapped_struct_dict: typing.Dict[str, Struct] = {}
    for s in structs:
        s[:] = sorted(s, key=get_start)
        ws = Struct(s)
        wrapped_struct_dict[ws.name] = ws

    for ws in wrapped_struct_dict.values():
        ws.find_deps(wrapped_struct_dict, enum_dict)

    sorted_structs: typing.OrderedDict[str, et.Element] = OrderedDict()
    for s in structs:
        _s = wrapped_struct_dict[s.attrib['name']]
        _s.add_xml(sorted_structs)

    instructions = sorted(xml.findall('./instruction'), key=get_name)
    for i in instructions:
        i[:] = sorted(i, key=get_start)

    registers = sorted(xml.findall('./register'), key=get_name)
    for r in registers:
        r[:] = sorted(r, key=get_start)

    new_elems = (imports + enums + list(sorted_structs.values()) +
                 instructions + registers)
    for n in new_elems:
        process_attribs(n)
    genxml[:] = new_elems


# `default_imports` documents which files should be imported for our
# genxml files. This is only useful if a genxml file does not already
# include imports.
#
# Basically, this allows the genxml_import.py tool used with the
# --import switch to know which files should be added as an import.
# (genxml_import.py uses GenXml.add_xml_imports, which relies on
# `default_imports`.)
default_imports = OrderedDict([
    ('gen40.xml', ()),
    ('gen45.xml', ('gen40.xml',)),
    ('gen50.xml', ('gen45.xml',)),
    ('gen60.xml', ('gen50.xml',)),
    ('gen70.xml', ('gen60.xml',)),
    ('gen75.xml', ('gen70.xml',)),
    ('gen80.xml', ('gen75.xml',)),
    ('gen90.xml', ('gen80.xml',)),
    ('gen110.xml', ('gen90.xml',)),
    ('gen120.xml', ('gen110.xml',)),
    ('gen125.xml', ('gen120.xml',)),
    ('gen200.xml', ('gen125.xml',)),
    ('gen200_rt.xml', ('gen125_rt.xml',)),
    ('gen300.xml', ('gen200.xml',)),
    ('gen300_rt.xml', ('gen200_rt.xml',)),
    ])
known_genxml_files = list(default_imports.keys())


def genxml_path_to_key(path):
    try:
        return known_genxml_files.index(path.name)
    except ValueError:
        return len(known_genxml_files)


def sort_genxml_files(files):
    files.sort(key=genxml_path_to_key)

class GenXml(object):
    def __init__(self, filename, import_xml=False, files=None):
        if files is not None:
            self.files = files
        else:
            self.files = set()
        self.filename = pathlib.Path(filename)

        # Assert that the file hasn't already been loaded which would
        # indicate a loop in genxml imports, and lead to infinite
        # recursion.
        assert self.filename not in self.files

        self.files.add(self.filename)
        self.et = et.parse(self.filename)
        if import_xml:
            self.merge_imported()

    def process_imported(self, merge=False, drop_dupes=False):
        """Processes imported genxml files.

        This helper function scans imported genxml files and has two
        mutually exclusive operating modes.

        If `merge` is True, then items will be merged into the
        `self.et` data structure.

        If `drop_dupes` is True, then any item that is a duplicate to
        an item imported will be droped from the `self.et` data
        structure. This is used by `self.optimize_xml_import` to
        shrink the size of the genxml file by reducing duplications.

        """
        assert merge != drop_dupes
        orig_elements = set(self.et.getroot())
        name_and_obj = lambda i: (get_name(i), i)
        filter_ty = lambda s: filter(lambda i: i.tag == s, orig_elements)
        filter_ty_item = lambda s: dict(map(name_and_obj, filter_ty(s)))

        # orig_by_tag stores items defined directly in the genxml
        # file. If a genxml item is defined in the genxml directly,
        # then any imported items of the same name are ignored.
        orig_by_tag = {
            'enum': filter_ty_item('enum'),
            'struct': filter_ty_item('struct'),
            'instruction': filter_ty_item('instruction'),
            'register': filter_ty_item('register'),
        }

        for item in orig_elements:
            if item.tag == 'import':
                assert 'name' in item.attrib
                filename = os.path.split(item.attrib['name'])
                exceptions = set()
                for e in item:
                    assert e.tag == 'exclude'
                    exceptions.add(e.attrib['name'])
                # We should be careful to restrict loaded files to
                # those under the source or build trees. For now, only
                # allow siblings of the current xml file.
                assert filename[0] == '', 'Directories not allowed with import'
                filename = os.path.join(os.path.dirname(self.filename),
                                        filename[1])
                assert os.path.exists(filename), f'{self.filename} {filename}'

                # Here we load the imported genxml file. We set
                # `import_xml` to true so that any imports in the
                # imported genxml will be merged during the loading
                # process.
                #
                # The `files` parameter is a set of files that have
                # been loaded, and it is used to prevent any cycles
                # (infinite recursion) while loading imported genxml
                # files.
                genxml = GenXml(filename, import_xml=True, files=self.files)
                imported_elements = set(genxml.et.getroot())

                # `to_add` is a set of items that were imported an
                # should be merged into the `self.et` data structure.
                # This is only used when the `merge` parameter is
                # True.
                to_add = set()
                # `to_remove` is a set of items that can safely be
                # imported since the item is equivalent. This is only
                # used when the `drop_duped` parameter is True.
                to_remove = set()
                for i in imported_elements:
                    if i.tag not in orig_by_tag:
                        continue
                    if i.attrib['name'] in exceptions:
                        continue
                    if i.attrib['name'] in orig_by_tag[i.tag]:
                        if merge:
                            # An item with this same name was defined
                            # in the genxml directly. There we should
                            # ignore (not merge) the imported item.
                            continue
                    else:
                        if drop_dupes:
                            # Since this item is not the imported
                            # genxml, we can't consider dropping it.
                            continue
                    if merge:
                        to_add.add(i)
                    else:
                        assert drop_dupes
                        orig_element = orig_by_tag[i.tag][i.attrib['name']]
                        if not node_validator(i, orig_element):
                            continue
                        to_remove.add(orig_element)

                if len(to_add) > 0:
                    # Now that we have scanned through all the items
                    # in the imported genxml file, if any items were
                    # found which should be merged, we add them into
                    # our `self.et` data structure. After this it will
                    # be as if the items had been directly present in
                    # the genxml file.
                    assert len(to_remove) == 0
                    self.et.getroot().extend(list(to_add))
                    sort_xml(self.et)
                elif len(to_remove) > 0:
                    self.et.getroot()[:] = list(orig_elements - to_remove)
                    sort_xml(self.et)

    def merge_imported(self):
        """Merge imported items from genxml imports.

        Genxml <import> tags specify that elements should be brought
        in from another genxml source file. After this function is
        called, these elements will become part of the `self.et` data
        structure as if the elements had been directly included in the
        genxml directly.

        Items from imported genxml files will be completely ignore if
        an item with the same name is already defined in the genxml
        file.

        """
        self.process_imported(merge=True)

    def flatten_imported(self):
        """Flattens the genxml to not include any imports

        Essentially this helper will put the `self.et` into a state
        that includes all imported items directly, and does not
        contain any <import> tags. This is used by the
        genxml_import.py with the --flatten switch to "undo" any
        genxml imports.

        """
        self.merge_imported()
        root = self.et.getroot()
        imports = root.findall('import')
        for i in imports:
            root.remove(i)

    def add_xml_imports(self):
        """Adds imports to the genxml file.

        Using the `default_imports` structure, we add imports to the
        genxml file.

        """
        # `imports` is a set of filenames currently imported by the
        # genxml.
        imports = self.et.findall('import')
        imports = set(map(lambda el: el.attrib['name'], imports))
        new_elements = []
        self_flattened = copy.deepcopy(self)
        self_flattened.flatten_imported()
        old_names = { el.attrib['name'] for el in self_flattened.et.getroot() }
        for import_xml in default_imports.get(self.filename.name, tuple()):
            if import_xml in imports:
                # This genxml is already imported, so we don't need to
                # add it as an import.
                continue
            el = et.Element('import', {'name': import_xml})
            import_path = self.filename.with_name(import_xml)
            imported_genxml = GenXml(import_path, import_xml=True)
            imported_names = { el.attrib['name']
                               for el in imported_genxml.et.getroot()
                               if el.tag != 'import' }
            # Importing this genxml could add some new items. When
            # adding a genxml import, we don't want to add new items,
            # unless they were already in the current genxml. So, we
            # put them into a list of items to exclude when importing
            # the genxml.
            exclude_names = imported_names - old_names
            for n in sorted(exclude_names):
                el.append(et.Element('exclude', {'name': n}))
            new_elements.append(el)
        if len(new_elements) > 0:
            self.et.getroot().extend(new_elements)
            sort_xml(self.et)

    def optimize_xml_import(self):
        """Optimizes the genxml by dropping items that can be imported

        Scans genxml <import> tags, and loads the imported file. If
        any item in the imported file is a duplicate to an item in the
        genxml file, then it will be droped from the `self.et` data
        structure.

        """
        self.process_imported(drop_dupes=True)

    def filter_engines(self, engines):
        changed = False
        items = []
        for item in self.et.getroot():
            # When an instruction doesn't have the engine specified,
            # it is considered to be for all engines. Otherwise, we
            # check to see if it's tagged for the engines requested.
            if item.tag == 'instruction' and 'engine' in item.attrib:
                i_engines = set(item.attrib["engine"].split('|'))
                if not (i_engines & engines):
                    # Drop this instruction because it doesn't support
                    # the requested engine types.
                    changed = True
                    continue
            items.append(item)
        if changed:
            self.et.getroot()[:] = items

    def filter_symbols(self, symbol_list):
        symbols_allowed = {}
        for sym in symbol_list:
            symbols_allowed[sym] = sym

        changed = False
        items = []
        for item in self.et.getroot():
            if item.tag in ('instruction', 'struct', 'register') and \
               item.attrib['name'] not in symbols_allowed:
                # Drop the item from the tree
                changed = True
                continue
            items.append(item)
        if changed:
            self.et.getroot()[:] = items

    def sort(self):
        sort_xml(self.et)

    def sorted_copy(self):
        clone = copy.deepcopy(self)
        clone.sort()
        return clone

    def is_equivalent_xml(self, other):
        if len(self.et.getroot()) != len(other.et.getroot()):
            return False
        return all(node_validator(old, new)
                   for old, new in zip(self.et.getroot(), other.et.getroot()))

    def write_file(self):
        try:
            old_genxml = GenXml(self.filename)
            if self.is_equivalent_xml(old_genxml):
                return
        except Exception:
            pass

        b_io = io.BytesIO()
        et.indent(self.et, space='  ')
        self.et.write(b_io, encoding="utf-8", xml_declaration=True)
        b_io.write(b'\n')

        tmp = self.filename.with_suffix(f'{self.filename.suffix}.tmp')
        tmp.write_bytes(b_io.getvalue())
        tmp.replace(self.filename)
