# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import logging as log
from collections import OrderedDict
from functools import partial

from reggen.validate import check_bool, check_int, val_types

from .item import Node, NodeType
from .lib import simplify_addr
from .xbar import Xbar

# val_types = {
#     'd': ["int", "integer (binary 0b, octal 0o, decimal, hex 0x)"],
#     'x': ["xint", "x for undefined otherwise int"],
#     'b': [
#         "bitrange", "bit number as decimal integer, \
#                     or bit-range as decimal integers msb:lsb"
#     ],
#     'l': ["list", "comma separated list enclosed in `[]`"],
#     'ln': ["name list", 'comma separated list enclosed in `[]` of '\
#            'one or more groups that have just name and dscr keys.'\
#            ' e.g. `{ name: "name", desc: "description"}`'],
#     'lnw': ["name list+", 'name list that optionally contains a width'],
#     'lp': ["parameter list", 'parameter list having default value optionally'],
#     'g': ["group", "comma separated group of key:value enclosed in `{}`"],
#     'lg': ["list of group", "comma separated group of key:value enclosed in `{}`"\
#            " the second entry of the list is the sub group format"],
#     's': ["string", "string, typically short"],
#     't': ["text", "string, may be multi-line enclosed in `'''` "\
#           "may use `**bold**`, `*italic*` or `!!Reg` markup"],
#     'T': ["tuple", "tuple enclosed in ()"],
#     'pi': ["python int", "Native Python type int (generated)"],
#     'pb': ["python Bool", "Native Python type Bool (generated)"],
#     'pl': ["python list", "Native Python type list (generated)"],
#     'pe': ["python enum", "Native Python type enum (generated)"]
# }
addr = {
    'name': 'Address configuration',
    'description':
    '''Device Node address configuration. It contains the base address and the size in bytes.
''',
    'required': {
        'base_addr':
        ['d', 'Base address of the device. It is required for the device'],
        'size_byte':
        ['d', 'Memory space of the device. It is required for the device'],
    },
    'optional': {},
    'added': {}
}

node = {
    'name': 'Node configuration',
    'description': '''
Crossbar node description. It can be host, device, or internal nodes.
''',
    'required': {
        'name': ['s', 'Module instance name'],
        'stub': ['pb', 'Real node or stub.  Stubs only occupy address ranges'],
        'type': [
            's',
            'Module type: {"host", "device", "async", "socket_1n", "socket_m1"}'
        ],
    },
    'optional': {
        'clock': ['s', 'main clock of the port'],
        'reset': ['s', 'main reset of the port'],
        'pipeline': ['pb', 'If true, pipeline is added in front of the port'],
        'pipeline_byp': [
            'pb', 'Pipeline bypass. If true, '
            'request/response are not latched'
        ],
        'inst_type': ['s', 'Instance type'],
        'xbar': ['pb', 'If true, the node is connected to another Xbar'],
        'addr_range': ['lg', addr]
    },
    'added': {}
}

root = {
    'name': 'Top configuration',
    'description': '''
Crossbar configuration format.
''',
    'required': {
        'name': ['s', 'Name of the crossbar'],
        'clock': [
            's', 'Main clock. Internal components use this clock.'
            ' If not specified, it is assumed to be in main clock domain'
        ],
        'reset': ['s', 'Main reset'],
        'connections': [
            'g',
            "List of edge. Key is host, entry in value list is device"
        ],
        'clock_connections': ['g', 'list of clocks'],
        'nodes': ['lg', node]
    },
    'optional': {
        'type': ['s', 'Indicate Hjson type. "xbar" always if exist'],
        'clock_group': ['s', "Remnant from auto-generation scripts. Ignore."],
        'clock_srcs': ['g', "Remnant from auto-generation scripts. Ignore."],
        'domain': ['s', 'Power domain for the crossbar']
    },
    'added': {
        'reset_connections': [
            'g', "Generated by topgen. Key is the reset signal inside IP"
            " and value is the top reset signal"
        ],
    }
}


def check_keys(obj, control, prefix=""):
    """ Check the keys recursively.

    The control parameter is a control group to check obj data structure.
    """
    error = 0

    # required
    for k, v in control["required"].items():
        if k not in obj:
            error += 1
            log.error(prefix + " missing required key " + k)

    # Check every fields' correctness
    for k, v in obj.items():
        checker = ['', '']
        prefix_name = prefix + " " + k

        if k in control["required"]:
            checker = control["required"][k]
        elif k in control["optional"]:
            checker = control["optional"][k]
        elif k in control["added"]:
            log.warning(prefix + " contains generated key " + k)
            checker = control["added"][k]
        else:
            log.warning(prefix + " contains extra key " + k)
            continue

        # Type and value check
        if checker[0] is not None and checker[0] not in val_types:
            log.error(prefix +
                      " field {} is undefined type. Check val_types {}".format(
                          k, checker[0]))
        if checker[0] is None:
            pass
        elif checker[0] == 'lg':
            # List of subgroup
            error += sum(
                map(
                    partial(check_keys, control=checker[1],
                            prefix=prefix_name), obj[k]))
        elif checker[0] == 'g':
            # if second entry isn't string type, call recursively
            if isinstance(checker[1], str):
                log.info(
                    "Skipping {} as no further control group is given".format(
                        prefix_name))
                continue

            error += check_keys(obj=obj[k],
                                control=checker[1],
                                prefix=prefix_name)

        elif checker[0] == 'd':
            int_v, err = check_int(obj[k], prefix_name)
            if err:
                error += 1

        elif checker[0] == 's' or checker[0] == 't':
            # don't care the string
            pass

        elif checker[0] == 'pb':
            b_v, err = check_bool(obj[k], prefix_name)
            if err:
                error += 1

        elif checker[0] == 'l':
            if not isinstance(obj[k], list):
                error += 1
        else:
            log.error(prefix_name +
                      " is not supported in this configuration format")

    return error


def get_nodetype(t):  # t: str -> NodeType
    if t == "host":
        return NodeType.HOST
    elif t == "device":
        return NodeType.DEVICE
    elif t == "async_fifo":
        return NodeType.ASYNC_FIFO
    elif t == "socket_1n":
        return NodeType.SOCKET_1N
    elif t == "socket_m1":
        return NodeType.SOCKET_M1

    log.error("Cannot process type {}".format(t))
    raise


def checkNameExist(name, xbar):  # name: str -> xbar: Xbar -> bool
    return name.lower() in [x.name for x in xbar.nodes]


def isOverlap(range1, range2):  # Tuple[int,int] -> Tuple[int,int] -> bool
    return not (range2[1] < range1[0] or range2[0] > range1[1])


# Tuple[int,int] -> List[Tuple[]] -> bool
def checkAddressOverlap(addr, ranges):
    result = [x for x in ranges if isOverlap(x, addr)]
    return len(result) != 0


# this returns 1 if the size mask overlapps with the address base
def checkBaseSizeOverlap(addr_base, size):
    return ((size - 1) & addr_base)


def validate(obj: OrderedDict) -> Xbar:  # OrderedDict -> Xbar
    xbar = Xbar()
    xbar.name = obj["name"].lower()
    xbar.clock = obj["clock"].lower()
    xbar.reset = obj["reset"].lower()
    addr_ranges = []

    obj, err = validate_hjson(obj)  # validate Hjson format first
    if err > 0:
        log.error("Hjson structure error")
        return

    # collection of all clocks and resets of this xbar
    xbar.clocks = [clock for clock in obj["clock_connections"].keys()]
    xbar.resets = [reset for reset in obj["reset_connections"].keys()]

    # Nodes
    for nodeobj in obj["nodes"]:

        if checkNameExist(nodeobj["name"], xbar):
            log.error("Duplicated name: %s" % (nodeobj["name"]))
            raise SystemExit("Duplicated name in the configuration")

        clock = nodeobj["clock"].lower() if "clock" in nodeobj.keys(
        ) else xbar.clock

        reset = nodeobj["reset"].lower() if "reset" in nodeobj.keys(
        ) else xbar.reset

        if clock not in xbar.clocks:
            log.error(
                "Clock %s for module %s does not exist in xbar_%s, check xbar hjson"
                % (clock, nodeobj['name'], obj['name']))
            raise SystemExit("Clock does not exist")

        if reset not in xbar.resets:
            log.error(
                "Reset %s for module %s does not exist in xbar_%s, check xbar hjson"
                % (reset, nodeobj['name'], obj['name']))
            raise SystemExit("Reset does not exist")

        node = Node(name=nodeobj["name"].lower(),
                    node_type=get_nodetype(nodeobj["type"].lower()),
                    clock=clock,
                    reset=reset)

        if node.node_type == NodeType.DEVICE:
            node.xbar = nodeobj["xbar"]
            node.addr_range = []

            # Compact the address ranges
            if node.xbar:
                nodeobj["addr_range"] = simplify_addr(nodeobj, obj)

            for addr in nodeobj["addr_range"]:
                address_from = int(addr["base_addr"], 0)
                size = int(addr["size_byte"], 0)
                address_to = address_from + size - 1

                addr_entry = (address_from, address_to)

                if checkBaseSizeOverlap(address_from, size):
                    log.error(
                        "Size mask and base address are overlapping. "
                        " Check the config. Addr(0x%x - 0x%x)"
                        % (addr_entry[0], addr_entry[1]))
                    raise SystemExit("Base/size overlapping error occurred")

                if checkAddressOverlap(addr_entry, addr_ranges):
                    log.error(
                        "Address is overlapping. Check the config. Addr(0x%x - 0x%x)"
                        % (addr_entry[0], addr_entry[1]))
                    raise SystemExit("Address overlapping error occurred")

                addr_ranges.append(addr_entry)
                node.addr_range.append(addr_entry)

        if node.node_type in [NodeType.DEVICE, NodeType.HOST
                              ] and "pipeline" in nodeobj:
            node.pipeline = True if nodeobj["pipeline"].lower() in [
                "true", "1"
            ] else False
        else:
            node.pipeline = False
        if node.node_type in [NodeType.DEVICE, NodeType.HOST
                              ] and "pipeline_byp" in nodeobj:
            node.pipeline_byp = True if nodeobj["pipeline_byp"].lower() in [
                "true", "1"
            ] else False
        else:
            node.pipeline_byp = True
        xbar.nodes.append(node)

    # Edge
    for host in obj["connections"].keys():
        # host: [device]
        for device in obj["connections"][host]:
            xbar.connect_nodes(host.lower(), device.lower())

    return xbar


def validate_hjson(obj):
    if "type" not in obj:
        obj["type"] = "xbar"
    if "name" not in obj:
        log.error("Component has no name. Aborting.")
        return None, 1

    component = obj["name"]
    error = check_keys(obj, root, component)

    if error > 0:
        log.error("{} has top level error. Aborting".format(component))
        return None, error
    return obj, 0
