import json
import os
import jinja2
from concurrent.futures import ProcessPoolExecutor
from brian_dashboard_manager.templating.render import create_dropdown_panel
from brian_dashboard_manager.templating.helpers import \
    is_aggregate_interface, is_logical_interface, is_physical_interface, \
    num_generator, gridPos_generator, get_panel_fields, create_aggregate_panel


def get_nrens(interfaces):
    result = {}
    for interface in interfaces:

        description = interface.get('description', '').strip()

        nren_name = description.split(' ')[2].upper()

        nren = result.get(
            nren_name, {'AGGREGATES': [], 'SERVICES': [], 'PHYSICAL': []})

        interface_name = interface.get('name')
        host = interface.get('router', '')
        router = host.replace('.geant.net', '')
        panel_title = f"{router} - {{}} - {interface_name} - {description}"

        location = host.split('.')[1].upper()
        if is_aggregate_interface(interface):
            nren['AGGREGATES'].append({
                'interface': interface_name,
                'hostname': host,
                'alias': f"{location} - {nren_name} ({interface_name})"
            })

            # link aggregates are also shown
            # under the physical dropdown
            nren['PHYSICAL'].append({
                'title': panel_title,
                'hostname': host,
                'interface': interface_name
            })

        elif is_logical_interface(interface):
            nren['SERVICES'].append({
                'title': panel_title,
                'hostname': host,
                'interface': interface_name
            })
        elif is_physical_interface(interface):
            nren['PHYSICAL'].append({
                'title': panel_title,
                'hostname': host,
                'interface': interface_name
            })

        result[nren_name] = nren
    return result


id_gen = num_generator(start=1)

# aggregate panels have y=0, start generating at 1*height
gridPos = gridPos_generator(id_gen, start=1)


def get_panel_definitions(panels, datasource, errors=False):
    result = []
    for panel in panels:
        result.append(get_panel_fields(
            {**panel, **next(gridPos)}, 'traffic', datasource))
        if panel.get('has_v6', False):
            result.append(get_panel_fields(
                {**panel, **next(gridPos)}, 'IPv6', datasource))
        if errors:
            result.append(get_panel_fields(
                {**panel, **next(gridPos)}, 'errors', datasource))
    return result


def build_data(nren, data, datasource):
    global gridPos
    if len(data['AGGREGATES']) > 0:
        agg_panels = create_aggregate_panel(
            f'Aggregate - {nren}',
            gridPos_generator(id_gen, agg=True),
            data['AGGREGATES'], datasource)
    else:
        # if there's no aggregate panel(s), start other stuff at y=0.
        gridPos = gridPos_generator(id_gen, start=0)
        agg_panels = []
    services_dropdown = create_dropdown_panel('Services', **next(gridPos))
    service_panels = get_panel_definitions(data['SERVICES'], datasource)
    iface_dropdown = create_dropdown_panel('Interfaces', **next(gridPos))
    phys_panels = get_panel_definitions(data['PHYSICAL'], datasource, True)

    return {
        'nren_name': nren,
        'datasource': datasource,
        'aggregate_panels': agg_panels,
        'dropdown_groups': [
            {
                'dropdown': services_dropdown,
                'panels': service_panels,
            },
            {
                'dropdown': iface_dropdown,
                'panels': phys_panels,
            }
        ]
    }


def get_dashboard_data(interfaces, datasource):
    nren_data = get_nrens(interfaces)
    result = []
    with ProcessPoolExecutor(max_workers=4) as executor:
        for nren, data in nren_data.items():
            result.append(executor.submit(build_data, nren, data, datasource))
    return [r.result() for r in result]


def generate_nrens(interfaces, datasource):
    file = os.path.abspath(os.path.join(
        os.path.dirname(__file__),
        'templates',
        'nren_access',
        'nren-dashboard.json.j2'))

    with open(file) as f:
        template = jinja2.Template(f.read())

    for dashboard in get_dashboard_data(interfaces, datasource):
        rendered = template.render(dashboard)
        rendered = json.loads(rendered)
        rendered['uid'] = None
        rendered['id'] = None
        yield rendered