using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

namespace InfiniteWorld
{
    [CreateAssetMenu(menuName = "Infinite World/World Autotile Profile", fileName = "WorldAutotileProfile")]
    public class WorldAutotileProfile : ScriptableObject
    {
        public bool autoUpdatePaletteLayout = true;
        public bool autoRefreshGeneratedWorld = true;
        public TileBase baseGroundTile;
        public AutoTileDefinition wallTiles = new AutoTileDefinition();
        public List<EnvironmentTileEntry> environmentTiles = new List<EnvironmentTileEntry>();
        public List<RandomPrefabEntry> randomPrefabs = new List<RandomPrefabEntry>();

        public TileBase GetWallTile(AutoTileShape shape)
        {
            return wallTiles != null ? wallTiles.GetTile(shape) : null;
        }

        public bool HasAnyAssignedTiles()
        {
            if (baseGroundTile != null)
            {
                return true;
            }

            if (wallTiles != null && wallTiles.HasAnyAssignedTiles())
            {
                return true;
            }

            if (environmentTiles != null)
            {
                for (int i = 0; i < environmentTiles.Count; i++)
                {
                    if (environmentTiles[i] != null && environmentTiles[i].tile != null)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
    }

    public enum AutoTileShape
    {
        Center,
        Top,
        Right,
        Bottom,
        Left,
        OuterTopLeft,
        OuterTopRight,
        OuterBottomRight,
        OuterBottomLeft,
        InnerTopLeft,
        InnerTopRight,
        InnerBottomRight,
        InnerBottomLeft
    }

    [Serializable]
    public class AutoTileDefinition
    {
        public TileBase center;
        public TileBase top;
        public TileBase right;
        public TileBase bottom;
        public TileBase left;
        public TileBase outerTopLeft;
        public TileBase outerTopRight;
        public TileBase outerBottomRight;
        public TileBase outerBottomLeft;
        public TileBase innerTopLeft;
        public TileBase innerTopRight;
        public TileBase innerBottomRight;
        public TileBase innerBottomLeft;

        public TileBase GetTile(AutoTileShape shape)
        {
            TileBase tile = shape switch
            {
                AutoTileShape.Center => center,
                AutoTileShape.Top => top,
                AutoTileShape.Right => right,
                AutoTileShape.Bottom => bottom,
                AutoTileShape.Left => left,
                AutoTileShape.OuterTopLeft => outerTopLeft,
                AutoTileShape.OuterTopRight => outerTopRight,
                AutoTileShape.OuterBottomRight => outerBottomRight,
                AutoTileShape.OuterBottomLeft => outerBottomLeft,
                AutoTileShape.InnerTopLeft => innerTopLeft,
                AutoTileShape.InnerTopRight => innerTopRight,
                AutoTileShape.InnerBottomRight => innerBottomRight,
                AutoTileShape.InnerBottomLeft => innerBottomLeft,
                _ => center
            };

            return tile ?? center;
        }

        public TileBase GetAssignedTile(AutoTileShape shape)
        {
            return shape switch
            {
                AutoTileShape.Center => center,
                AutoTileShape.Top => top,
                AutoTileShape.Right => right,
                AutoTileShape.Bottom => bottom,
                AutoTileShape.Left => left,
                AutoTileShape.OuterTopLeft => outerTopLeft,
                AutoTileShape.OuterTopRight => outerTopRight,
                AutoTileShape.OuterBottomRight => outerBottomRight,
                AutoTileShape.OuterBottomLeft => outerBottomLeft,
                AutoTileShape.InnerTopLeft => innerTopLeft,
                AutoTileShape.InnerTopRight => innerTopRight,
                AutoTileShape.InnerBottomRight => innerBottomRight,
                AutoTileShape.InnerBottomLeft => innerBottomLeft,
                _ => null
            };
        }

        public bool HasAnyAssignedTiles()
        {
            return center != null ||
                   top != null ||
                   right != null ||
                   bottom != null ||
                   left != null ||
                   outerTopLeft != null ||
                   outerTopRight != null ||
                   outerBottomRight != null ||
                   outerBottomLeft != null ||
                   innerTopLeft != null ||
                   innerTopRight != null ||
                   innerBottomRight != null ||
                   innerBottomLeft != null;
        }
    }

    [Serializable]
    public class EnvironmentTileEntry
    {
        public string id = "Environment";
        public TileBase tile;
        [Min(0f)] public float weight = 1f;
    }

    [Serializable]
    public class RandomPrefabEntry
    {
        public string id = "RandomPrefab";
        public GameObject prefab;
        [Min(0f)] public float weight = 1f;
    }
}
