"""Draw the six Holton-McKay duals and their witness Even Level Graphs as
crossing-free planar drawings (networkx planar_layout, Chrobak-Payne).
Two figures:
  n21_elgs.png  -- the six witness Even Level Graphs, parity-coloured,
                   with the edges flipped by the bridge switches dashed red;
  n21_duals.png -- the six resulting duals, parity-coloured (same fixed
                   parity labelling), with the introduced bridge edges green.
Reads experiments/witnesses/dual_*.json. ELG and dual are drawn with
independent planar layouts so neither has any edge crossing.
"""
import sys
import os
import json
sys.path.insert(0, '/Users/didericis/Code/math-research/papers/'
                'level_resolutions_of_maximal_planar_graphs/experiments')
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import networkx as nx
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

HERE = os.path.dirname(os.path.abspath(__file__))
WDIR = os.path.join(HERE, 'witnesses')
FDIR = os.path.join(HERE, '..', 'figures')

EVEN_C = '#9ecae1'   # even-parity vertices
ODD_C = '#fdae6b'    # odd-parity vertices


def load(i):
    return json.load(open(os.path.join(WDIR, f'dual_{i}.json')))


def graph_of(edges, labels):
    G = nx.Graph()
    G.add_nodes_from(int(v) for v in labels)
    G.add_edges_from((a, b) for a, b in edges)
    return G


def draw(ax, G, labels, highlight, hcolor, hstyle, title):
    pos = nx.planar_layout(G)
    colors = [EVEN_C if labels[str(v)] == 0 else ODD_C for v in G.nodes()]
    hl = {frozenset(e) for e in highlight}
    plain = [e for e in G.edges() if frozenset(e) not in hl]
    nx.draw_networkx_edges(G, pos, edgelist=plain, ax=ax,
                           edge_color='#b0b0b0', width=0.8)
    if hl:
        nx.draw_networkx_edges(G, pos, edgelist=[tuple(e) for e in hl], ax=ax,
                               edge_color=hcolor, width=2.4, style=hstyle)
    nx.draw_networkx_nodes(G, pos, node_color=colors, node_size=200,
                           edgecolors='#444444', linewidths=0.6, ax=ax)
    nx.draw_networkx_labels(G, pos, font_size=8, ax=ax)
    ax.set_title(title, fontsize=10)
    ax.margins(0.12)
    ax.axis('off')


def legend(fig, kind):
    handles = [
        Line2D([0], [0], marker='o', color='w', markerfacecolor=EVEN_C,
               markeredgecolor='#444', markersize=9, label='even parity'),
        Line2D([0], [0], marker='o', color='w', markerfacecolor=ODD_C,
               markeredgecolor='#444', markersize=9, label='odd parity'),
    ]
    if kind == 'elg':
        handles.append(Line2D([0], [0], color='#d62728', lw=2.4, ls='dashed',
                              label='edge flipped by a bridge switch'))
    else:
        handles.append(Line2D([0], [0], color='#2ca02c', lw=2.4,
                              label='bridge edge introduced'))
    fig.legend(handles=handles, loc='lower center', ncol=3, fontsize=9,
               frameon=False)


def main():
    os.makedirs(FDIR, exist_ok=True)

    # Figure 1: the six witness Even Level Graphs (flipped edges red dashed)
    fig, axes = plt.subplots(2, 3, figsize=(19, 12))
    for i, ax in zip(range(6), axes.flat):
        d = load(i)
        G = graph_of(d['elg_edges'], d['labels'])
        removed = [s['remove'] for s in d['bridge_switches']]
        k = d['num_bridge_switches']
        sub = (f"{k} bridge switch" + ("es" if k != 1 else "")
               if k else "Even Level Graph outright")
        draw(ax, G, d['labels'], removed, '#d62728', 'dashed',
             f"dual {i}: ELG (source {d['elg_source']})\n{sub}")
    legend(fig, 'elg')
    fig.tight_layout(rect=(0, 0.04, 1, 1))
    p1 = os.path.join(FDIR, 'n21_elgs.png')
    fig.savefig(p1, dpi=160)
    plt.close(fig)
    print(f'wrote {p1}')

    # Figure 2: the six resulting duals (introduced bridge edges green)
    fig, axes = plt.subplots(2, 3, figsize=(19, 12))
    for i, ax in zip(range(6), axes.flat):
        d = load(i)
        G = graph_of(d['dual_edges'], d['labels'])
        added = [s['add'] for s in d['bridge_switches']]
        draw(ax, G, d['labels'], added, '#2ca02c', 'solid', f"dual {i}")
    legend(fig, 'dual')
    fig.tight_layout(rect=(0, 0.04, 1, 1))
    p2 = os.path.join(FDIR, 'n21_duals.png')
    fig.savefig(p2, dpi=160)
    plt.close(fig)
    print(f'wrote {p2}')


if __name__ == '__main__':
    main()
