using Microsoft.Msagl.Drawing;
using Microsoft.Msagl.GraphViewerGdi;
using My.Collections;
using System;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace ColoringLandkarte;

class Program
{
    static void Main()
    {
        var graph = new ColoredGraph<string>();

        var BB = graph.AddNode("BB");
        var HE = graph.AddNode("HE");
        var SH = graph.AddNode("SH");
        var HH = graph.AddNode("HH");
        var MV = graph.AddNode("MV");
        var HB = graph.AddNode("HB");
        var NI = graph.AddNode("NI");
        var BE = graph.AddNode("BE");
        var ST = graph.AddNode("ST");
        var NW = graph.AddNode("NW");
        var TH = graph.AddNode("TH");
        var SN = graph.AddNode("SN");
        var RP = graph.AddNode("RP");
        var SL = graph.AddNode("SL");
        var BW = graph.AddNode("BW");
        var BY = graph.AddNode("BY");

        graph.AddEdge(SH, MV);
        graph.AddEdge(SH, HH);
        graph.AddEdge(SH, NI);
        graph.AddEdge(HH, NI);
        graph.AddEdge(MV, NI);
        graph.AddEdge(MV, BB);
        graph.AddEdge(NI, HB);
        graph.AddEdge(NI, BB);
        graph.AddEdge(NI, ST);
        graph.AddEdge(NI, TH);
        graph.AddEdge(NI, HE);
        graph.AddEdge(NI, NW);
        graph.AddEdge(BB, BE);
        graph.AddEdge(BB, ST);
        graph.AddEdge(BB, SN);
        graph.AddEdge(ST, SN);
        graph.AddEdge(ST, TH);
        graph.AddEdge(SN, TH);
        graph.AddEdge(SN, BY);
        graph.AddEdge(TH, BY);
        graph.AddEdge(TH, HE);
        graph.AddEdge(HE, NW);
        graph.AddEdge(HE, RP);
        graph.AddEdge(HE, BW);
        graph.AddEdge(HE, BY);
        graph.AddEdge(NW, RP);
        graph.AddEdge(RP, SL);
        graph.AddEdge(RP, BW);
        graph.AddEdge(BW, BY);

        graph.BacktrackingColoring();

        foreach (dynamic n in graph.Nodes)
        {
            Console.WriteLine($"{n.Item}: {n.Color} Color");
        }

        ShowGraph(graph);
        string s = graph.GenerateDotRepresentation();
    }

    static void ShowGraph<T>(Graph<T> graph)
    {
        using var form = new Form();
        using var viewer = new GViewer() { ToolBarIsVisible = false };
        var g = new Microsoft.Msagl.Drawing.Graph { Directed = graph.Directed };

        foreach (dynamic node in graph.Nodes)
        {
            string label1 = node.Item?.ToString() ?? "";
            var node1 = g.AddNode(label1);
            if (node.Color != null) node1.Attr.FillColor = Colors[node.Color];

            for (int i = 0; i < node.Neighbors.Count; i++)
            {
                var neighbor = node.Neighbors[i];
                string label2 = neighbor.Item?.ToString() ?? "";
                var weight = node.Weights[i]?.ToString() ?? "";

                var node2 = g.AddNode(label2);
                if (graph.Directed == false &&
                    g.Edges.Where(g => g.Source == label2 && g.Target == label1).Count() > 0)
                    continue;

                Edge edge = g.AddEdge(label1, weight, label2);
                edge.Attr.ArrowheadAtTarget = ArrowStyle.None;
                edge.Attr.ArrowheadAtSource = ArrowStyle.None;

                if (edge.Label != null) edge.Label.FontSize = 6;
            }
        }
        viewer.Graph = g;

        form.SuspendLayout();
        viewer.Dock = DockStyle.Fill;
        form.Controls.Add(viewer);
        form.ResumeLayout();
        form.ShowDialog();
    }
    static Color[] Colors
    {
        get
        {
            var t = typeof(Color);
            PropertyInfo[] properties = t.GetProperties(BindingFlags.Static | BindingFlags.Public);

            var colors = new Color[properties.Length];

            int index = 0;
            for (int i = 0; i < properties.Length; i++)
            {
                var prop = properties[i];

                Color? colorValue = prop.GetValue(null) as Color?;
                if (colorValue.HasValue)
                    colors[index++] = colorValue.Value;
            }
            return colors;
        }
    }
}