using Godot;
using System;
using System.Collections.Generic;

#nullable enable
public class LevelPattern  {
    public TileMapPattern Level { get; }

    public TileSet Solid1 { get; }
    public TileSet? Solid2 { get; init; }

    public TileSet Background1 { get; }
    public TileSet? Background2 { get; init; }

    public record Connection(int Length, bool IsHorizontal) { public bool IsVertical => !IsHorizontal; }

    public Connection[] Connections { get; }

    public Dictionary<Vector2I, Template.Tile> TranslationMap { get; }

    public class Template {
        public readonly record struct Solid(int Id);
        public readonly record struct Background(int Id);
        public readonly record struct Enemy(int Id);
        public readonly record struct Item(int Id);
        public readonly record struct Decoration(int Id);
        public readonly record struct MultiTile(Tile NonOverlappable, OverlappableTile[] Overlappable);
        public readonly record struct Any;
        public readonly union OverlappableTile(Enemy, Item, Decoration);
        public readonly union Tile(Solid, Any, Background, Enemy, Item, Decoration, MultiTile) {
            public bool IsAir() {
                if (this is Any or Background or Enemy or Item or Decoration) return true;
                if (this is MultiTile mt) {
                    do {
                        if (mt.NonOverlappable is MultiTile _mt)
                            mt = _mt;
                        else
                            return mt.NonOverlappable is Any or Background or Enemy or Item or Decoration;
                    } while (true);
                }
                return false;
            }
        }
    }

    public LevelPattern(TileMapPattern pattern, TileSet solid1, TileSet background1) {
        Level = pattern;
        Solid1 = solid1;
        Background1 = background1;

        // Connections = CalculateConnections(pattern);
    }


    record struct ScanInfo(int XFrom, int XTo, int YFrom, int YTo);
    public static Connection[] CalculateConnections(TileMapPattern pattern, Dictionary<Vector2I, Template.Tile> translations) {
        var current = Vector2I.Zero;
        var size = pattern.GetSize();
        
        // scan borders
        Span<ScanInfo> borders = stackalloc ScanInfo[] {
            new ScanInfo(current.X, size.X, current.Y, current.Y), // top-horiz
            new ScanInfo(current.X, current.X, current.Y, size.Y), // left-vert
            new ScanInfo(current.X, size.X, size.Y, size.Y), // bottom-horiz
            new ScanInfo(size.X, size.X, current.Y, size.Y) // right-vert
        };

        List<Connection> connections = [];
        foreach(var border in borders) {
            int xrun = 0;
            for(int x = border.XFrom; x < border.XTo; x++) {
                int yrun = 0;
                for(int y = border.YFrom; y < border.YTo; y++) {
                    var cell = translations[pattern.GetCellAtlasCoords(new Vector2I(x, y))];
                    if (cell.IsAir())
                        yrun++;
                    else if (yrun > 0) { 
                        connections.Add(new Connection(
                            yrun, IsHorizontal: false
                        ));
                        yrun = 0;
                    }
                }

                if (border.YFrom == border.YTo) {
                    // horizontal run
                    var cell = translations[pattern.GetCellAtlasCoords(new Vector2I(x, border.YFrom))];
                    if (cell.IsAir())
                        xrun++;
                    else if (xrun > 0) {
                        connections.Add(new Connection(
                            xrun, IsHorizontal: true
                        ));
                        xrun = 0;
                    }
                }
            }
        }
        
        return connections.ToArray();
    }

}

#nullable restore