import petl
from anytree import AnyNode


def make_node(record,
              nodes,
              id_field=None,
              parent_id_field=None):

    if id_field not in record.flds:
        raise Exception(f'field {id_field} '
                        'is not defined.')

    if parent_id_field not in record.flds:
        raise Exception(f'field {parent_id_field} '
                        f'is not defined')

    _id = record[id_field]

    payload = {
        'row': record,
    }

    parent_id = record[parent_id_field]
    parent_node = None

    if parent_id:
        parent_node = nodes[parent_id]
        payload['parent'] = parent_node

    node = nodes.setdefault(_id, AnyNode(id=_id, **payload))

    if parent_node:
        node.parent = parent_node

    node.row = record

    return node


def make_tree(nodes,
              sub_nodes_key='sub_resources',
              id_field=None):
    '''Take a list of nodes and add all of the children to a key,
    defaulting to 'sub_resources'
    '''

    for key, node in nodes.items():

        row = {'tree_id': node.row[id_field]}

        row[sub_nodes_key] = [subnode.row for subnode in node.children]
        yield row


def build_tree(table, id_field, parent_id_field,
               sub_fieldname):
    '''
    Take the table, create a tree based on the parent_id_field
    '''
    # Using anytree https://github.com/c0fec0de/anytree

    # root = AnyNode(id="root")
    # s0 = AnyNode(id="sub0", parent=root)
    # s0b = AnyNode(id="sub0B", parent=s0, foo=4, bar=109)
    # s0a = AnyNode(id="sub0A", parent=s0)
    # s1 = AnyNode(id="sub1", parent=root)
    # s1a = AnyNode(id="sub1A", parent=s1)
    # s1b = AnyNode(id="sub1B", parent=s1, bar=8)
    # s1c = AnyNode(id="sub1C", parent=s1)
    # s1ca = AnyNode(id="sub1Ca", parent=s1c)

    nodes = {}

    # for row in records(table):

    for row in petl.records(table):
        make_node(row, nodes,
                  id_field=id_field,
                  parent_id_field=parent_id_field)

    tree = make_tree(nodes,
                     sub_nodes_key=sub_fieldname,
                     id_field=id_field)

    tree_dicts = petl.fromdicts(tree)

    table = table.leftjoin(tree_dicts,
                           lkey=id_field,
                           rkey='tree_id')

    table = table.convert(sub_fieldname, lambda v: v or [])

    return table
