using System.Collections.Generic;
using UnityEngine;

namespace Editor.GON.StageEditor
{
    public sealed class StagePaletteEntry
    {
        public string id;
        public string displayName;
        public StageLogicalLayer layer;

        public bool paintsStructural;
        public StructuralCellKind structuralKind;

        public StageObjectKind objectKind;
        public string typeId;
        public string prefabId;

        public Vector2Int defaultSize = Vector2Int.one;
        public Vector2Int minSize = Vector2Int.one;
        public Vector2Int maxSize = new(32, 32);
        public bool resizable;
        public bool cutsGround;
        public bool blocksMovement;

        public static StagePaletteEntry Structural(string id, string name, StructuralCellKind kind)
        {
            return new StagePaletteEntry
            {
                id = id,
                displayName = name,
                layer = StageLogicalLayer.Structural,
                paintsStructural = true,
                structuralKind = kind,
                defaultSize = Vector2Int.one,
                minSize = Vector2Int.one,
                maxSize = new Vector2Int(64, 64),
                resizable = true
            };
        }
        
        public static StagePaletteEntry Object(
            string id,
            string name,
            StageLogicalLayer layer,
            StageObjectKind kind,
            string typeId,
            Vector2Int defaultSize = default,
            Vector2Int min = default,
            Vector2Int max = default)
        {
            var kindDefault = StageObjectDefinition.GetDefaultSize(kind);
            var kindMin = StageObjectDefinition.GetMinSize(kind);
            var kindMax = StageObjectDefinition.GetMaxSize(kind);

            return new StagePaletteEntry
            {
                id = id,
                displayName = name,
                layer = layer,
                paintsStructural = false,
                objectKind = kind,
                typeId = typeId,
                prefabId = string.Empty,
                defaultSize = defaultSize == default ? kindDefault : defaultSize,
                minSize = min == default ? kindMin : min,
                maxSize = max == default ? kindMax : max,
                resizable = StageObjectDefinition.IsKindResizable(kind)
            };
        }

        public static List<StagePaletteEntry> CreateBuiltInPalette()
        {
            var entries = new List<StagePaletteEntry>
            {
                Structural("struct_ground_slab", "Ground", StructuralCellKind.Ground),
                
                Structural("struct_ramp_front", "Ramp (Front)", StructuralCellKind.Ramp_Front),
                Structural("struct_ramp_left", "Ramp (Left)", StructuralCellKind.Ramp_Left),
                Structural("struct_ramp_right", "Ramp (Right)", StructuralCellKind.Ramp_Right),
                
                Structural("struct_stair_front", "Stair (Front)", StructuralCellKind.Stair_Front),
                Structural("struct_stair_left", "Stair (Left)", StructuralCellKind.Stair_Left),
                Structural("struct_stair_right", "Stair (Right)", StructuralCellKind.Stair_Right),

                Structural("struct_wall", "Wall", StructuralCellKind.Wall),
                
                // leave it as last as possible
                Structural("struct_empty", "Erase Structural", StructuralCellKind.Empty),
            };

            var trapFallingFloor = Object("trap_falling_floor",
                "Trap (Falling Floor)",
                StageLogicalLayer.Design,
                StageObjectKind.Trap_FallingFloor,
                "trap_falling_floor",
                defaultSize: Vector2Int.one);
            trapFallingFloor.cutsGround = true;
            trapFallingFloor.blocksMovement = true;
            entries.Add(trapFallingFloor);

            var socketEast = Object("socket_east_standard", 
                "Socket East",
                StageLogicalLayer.Design,
                StageObjectKind.SocketEast,
                "socket_east_standard",
                new Vector2Int(1, 4));
            socketEast.blocksMovement = false;
            entries.Add(socketEast);
            
            var socketNorth = Object("socket_north_standard", 
                "Socket North",
                StageLogicalLayer.Design,
                StageObjectKind.SocketNorth,
                "socket_north_standard",
                new Vector2Int(4, 1));
            socketNorth.blocksMovement = false;
            entries.Add(socketNorth);
            
            var socketSouth = Object("socket_south_standard", 
                "Socket South",
                StageLogicalLayer.Design,
                StageObjectKind.SocketSouth,
                "socket_south_standard",
                new Vector2Int(4, 1));
            socketSouth.blocksMovement = false;
            entries.Add(socketSouth);

            var socketWest = Object("socket_west_standard", 
                "Socket West",
                StageLogicalLayer.Design,
                StageObjectKind.SocketWest,
                "socket_west_standard",
                new Vector2Int(1, 4));
            socketWest.blocksMovement = false;
            entries.Add(socketWest);

            // entries.Add(Object("interactable", "Interactable", StageLogicalLayer.Design, StageObjectKind.Interactable, "interactable", Vector2Int.one));
            // entries.Add(Object("portal", "Portal", StageLogicalLayer.Design, StageObjectKind.Portal, "portal", new Vector2Int(2, 2)));
            entries.Add(Object("camera_boundary", 
                "Camera Boundary",
                StageLogicalLayer.Camera,
                StageObjectKind.CameraBoundary, 
                "camera_boundary",
                defaultSize: new Vector2Int(8, 5),
                min: new Vector2Int(8, 5)));
            // entries.Add(Object("spawn_player", "Player Spawn", StageLogicalLayer.Markers, StageObjectKind.Spawn, "player_spawn", Vector2Int.one));
            // entries.Add(Object("elevator", "Elevator", StageLogicalLayer.Markers, StageObjectKind.Elevator, "elevator", new Vector2Int(2, 2)));
            // entries.Add(Object("marker", "Marker", StageLogicalLayer.Markers, StageObjectKind.Marker, "marker", Vector2Int.one));

            return entries;
        }
    }
}
