"""
Generate Slipnet graph visualization (Figure 1)
Shows conceptual depth as node color gradient, with key Slipnet nodes and connections.
"""

import matplotlib.pyplot as plt
import networkx as nx
import numpy as np

# Define key Slipnet nodes with their conceptual depths
nodes = {
    # Letters (depth 10)
    'a': 10, 'b': 10, 'c': 10, 'd': 10, 'z': 10,
    # Numbers (depth 30)
    '1': 30, '2': 30, '3': 30,
    # String positions (depth 40)
    'leftmost': 40, 'rightmost': 40, 'middle': 40, 'single': 40,
    # Directions (depth 40)
    'left': 40, 'right': 40,
    # Alphabetic positions (depth 60)
    'first': 60, 'last': 60,
    # Bond types (depth 50-80)
    'predecessor': 50, 'successor': 50, 'sameness': 80,
    # Group types (depth 50-80)
    'predecessorGroup': 50, 'successorGroup': 50, 'samenessGroup': 80,
    # Relations (depth 90)
    'identity': 90, 'opposite': 90,
    # Categories (depth 20-90)
    'letterCategory': 30, 'stringPositionCategory': 70,
    'directionCategory': 70, 'bondCategory': 80, 'length': 60,
}

# Define edges with their link lengths (inverse = strength)
edges = [
    # Letter to letterCategory
    ('a', 'letterCategory', 97), ('b', 'letterCategory', 97),
    ('c', 'letterCategory', 97), ('d', 'letterCategory', 97),
    ('z', 'letterCategory', 97),

    # Successor/predecessor relationships
    ('a', 'b', 50), ('b', 'c', 50), ('c', 'd', 50),
    ('b', 'a', 50), ('c', 'b', 50), ('d', 'c', 50),

    # Bond types to bond category
    ('predecessor', 'bondCategory', 60), ('successor', 'bondCategory', 60),
    ('sameness', 'bondCategory', 30),

    # Group types
    ('sameness', 'samenessGroup', 30),
    ('predecessor', 'predecessorGroup', 60),
    ('successor', 'successorGroup', 60),

    # Opposite relations
    ('left', 'right', 80), ('right', 'left', 80),
    ('first', 'last', 80), ('last', 'first', 80),

    # Position relationships
    ('left', 'directionCategory', 50), ('right', 'directionCategory', 50),
    ('leftmost', 'stringPositionCategory', 50),
    ('rightmost', 'stringPositionCategory', 50),
    ('middle', 'stringPositionCategory', 50),

    # Slippable connections
    ('left', 'leftmost', 90), ('leftmost', 'left', 90),
    ('right', 'rightmost', 90), ('rightmost', 'right', 90),
    ('leftmost', 'first', 100), ('first', 'leftmost', 100),
    ('rightmost', 'last', 100), ('last', 'rightmost', 100),

    # Abstract relations
    ('identity', 'bondCategory', 50),
    ('opposite', 'bondCategory', 80),
]

# Create graph
G = nx.DiGraph()

# Add nodes with depth attribute
for node, depth in nodes.items():
    G.add_node(node, depth=depth)

# Add edges with link length
for source, target, length in edges:
    G.add_edge(source, target, length=length, weight=100-length)

# Create figure
fig, ax = plt.subplots(figsize=(16, 12))

# Use hierarchical layout based on depth
pos = {}
depth_groups = {}
for node in G.nodes():
    depth = G.nodes[node]['depth']
    if depth not in depth_groups:
        depth_groups[depth] = []
    depth_groups[depth].append(node)

# Position nodes by depth (y-axis) and spread horizontally
for depth, node_list in depth_groups.items():
    y = 1.0 - (depth / 100.0)  # Invert so shallow nodes at top
    for i, node in enumerate(node_list):
        x = (i - len(node_list)/2) / max(len(node_list), 10) * 2.5
        pos[node] = (x, y)

# Get node colors based on depth (blue=shallow/concrete, red=deep/abstract)
node_colors = [G.nodes[node]['depth'] for node in G.nodes()]

# Draw edges with thickness based on strength (inverse of link length)
edges_to_draw = G.edges()
edge_widths = [0.3 + (100 - G[u][v]['length']) / 100.0 * 3 for u, v in edges_to_draw]

nx.draw_networkx_edges(G, pos, edgelist=edges_to_draw, width=edge_widths,
                       alpha=0.3, arrows=True, arrowsize=10,
                       connectionstyle='arc3,rad=0.1', ax=ax)

# Draw nodes
nx.draw_networkx_nodes(G, pos, node_color=node_colors,
                       node_size=800, cmap='coolwarm',
                       vmin=0, vmax=100, ax=ax)

# Draw labels
nx.draw_networkx_labels(G, pos, font_size=8, font_weight='bold', ax=ax)

# Add colorbar
sm = plt.cm.ScalarMappable(cmap='coolwarm',
                           norm=plt.Normalize(vmin=0, vmax=100))
sm.set_array([])
cbar = plt.colorbar(sm, ax=ax, fraction=0.046, pad=0.04)
cbar.set_label('Conceptual Depth', rotation=270, labelpad=20, fontsize=12)

ax.set_title('Slipnet Graph Structure\n' +
             'Color gradient: Blue (concrete/shallow) → Red (abstract/deep)\n' +
             'Edge thickness: Link strength (inverse of link length)',
             fontsize=14, fontweight='bold', pad=20)
ax.axis('off')

plt.tight_layout()
plt.savefig('figure1_slipnet_graph.pdf', dpi=300, bbox_inches='tight')
plt.savefig('figure1_slipnet_graph.png', dpi=300, bbox_inches='tight')
print("Generated figure1_slipnet_graph.pdf and .png")
plt.close()
