using System;
using System.Collections.Generic;
using UnityEditor.U2D;
using UnityEngine;

namespace UnityEditor.Tilemaps
{
    /// <summary>
    /// The TileSet asset generates a Tile Palette and other supporting sub-assets from user inputs.
    /// </summary>
    [HelpURL("tilemaps/tile-palettes/tile-set-properties")]
    public class TileSet : ScriptableObject
    {
        /// <summary>
        /// Hexagon Layout for Grid
        /// </summary>
        public enum HexagonLayout
        {
            /// <summary>
            /// PointTop Hexagon Cells
            /// </summary>
            PointTop,
            /// <summary>
            /// FlatTop Hexagon Cells
            /// </summary>
            FlatTop,
        }

        /// <summary>
        /// Source Assets required by the TileSet to generate Tiles from a Texture.
        /// This includes a Texture and a script template to generate Tiles from the Texture.
        /// </summary>
        [Serializable]
        public class TextureSource
        {
            [SerializeField]
            private Texture2D m_Texture;
            [SerializeReference]
            private TileTemplate m_TileTemplate;

            /// <summary>
            /// Texture used to generate Tiles for the TileSet.
            /// </summary>
            public Texture2D texture
            {
                get => m_Texture;
                set => m_Texture = value;
            }
            /// <summary>
            /// Script Template used to generate Tiles from the corresponding Texture.
            /// A default template will be used if no script template is provided.
            /// </summary>
            public TileTemplate tileTemplate
            {
                get => m_TileTemplate;
                set => m_TileTemplate = value;
            }
        }
        [SerializeField]
        private List<TextureSource> m_TextureSources;

        /// <summary>
        /// List of TextureSources used by the TileSet
        /// </summary>
        public List<TextureSource> textureSources => m_TextureSources;

        // Atlas Settings
        [SerializeField]
        private bool m_CreateAtlas = true;

        [SerializeField]
        private ScriptablePacker m_ScriptablePacker = null;

        // Grid Settings
        [SerializeField]
        private GridLayout.CellLayout m_CellLayout = GridLayout.CellLayout.Rectangle;
        [SerializeField]
        private HexagonLayout m_HexagonLayout = HexagonLayout.PointTop;
        [SerializeField]
        private Vector3 m_CellSize = Vector3.one;
        [SerializeField]
        private GridPalette.CellSizing m_CellSizing = GridPalette.CellSizing.Automatic;
        [SerializeField]
        private TransparencySortMode m_TransparencySortMode = TransparencySortMode.Default;
        [SerializeField]
        private Vector3 m_TransparencySortAxis = new Vector3(0.0f, 0.0f, 1.0f);

        /// <summary>
        /// Cell Layout for the Tile Palette generated by the TileSet
        /// </summary>
        public GridLayout.CellLayout cellLayout
        {
            get => m_CellLayout;
            set => m_CellLayout = value;
        }

        /// <summary>
        /// Hexagonal Cell Layout for the Tile Palette generated by the TileSet
        /// </summary>
        public HexagonLayout hexagonLayout
        {
            get => m_HexagonLayout;
            set => m_HexagonLayout = value;
        }

        /// <summary>
        /// Cell Sizing for the Tile Palette generated by the TileSet
        /// </summary>
        public GridPalette.CellSizing cellSizing
        {
            get => m_CellSizing;
            set => m_CellSizing = value;
        }

        /// <summary>
        /// Cell Size for the Tile Palette generated by the TileSet
        /// </summary>
        public Vector3 cellSize
        {
            get => m_CellSize;
            set => m_CellSize = value;
        }

        /// <summary>
        /// Transparency Sort Mode for the Tile Palette generated by the TileSet
        /// </summary>
        public TransparencySortMode sortMode
        {
            get => m_TransparencySortMode;
            set => m_TransparencySortMode = value;
        }

        /// <summary>
        /// Transparency Sort Axis for the Tile Palette generated by the TileSet
        /// </summary>
        public Vector3 sortAxis
        {
            get => m_TransparencySortAxis;
            set => m_TransparencySortAxis = value;
        }

        /// <summary>
        /// Whether a SpriteAtlas should be created for the TileSet
        /// </summary>
        public bool createAtlas
        {
            get => m_CreateAtlas;
            set => m_CreateAtlas = value;
        }

        /// <summary>
        /// ScriptablePacker used when generated a SpriteAtlas for the TileSet
        /// </summary>
        public ScriptablePacker scriptablePacker
        {
            get => m_ScriptablePacker;
            set => m_ScriptablePacker = value;
        }

        [Serializable]
        internal struct SerializableSpriteImportData
        {
            [SerializeField] private string m_Name;
            [SerializeField] private Rect m_Rect;
            [SerializeField] private SpriteAlignment m_Alignment;
            [SerializeField] private Vector2 m_Pivot;
            [SerializeField] private Vector4 m_Border;
            [SerializeField] private float m_TessellationDetail;
            [SerializeField] private string m_SpriteID;
            [SerializeField] private List<Vector2[]> m_Outline;

            public string name { get { return m_Name; } set { m_Name = value; } }
            public Rect rect { get { return m_Rect; } set { m_Rect = value; } }
            public SpriteAlignment alignment { get { return m_Alignment; } set { m_Alignment = value; } }
            public Vector2 pivot { get { return m_Pivot; } set { m_Pivot = value; } }
            public Vector4 border { get { return m_Border; } set { m_Border = value; } }
            public List<Vector2[]> outline { get { return m_Outline; } set { m_Outline = value; } }
            public float tessellationDetail {get { return m_TessellationDetail; } set { m_TessellationDetail = value; } }
            public string spriteID {get { return m_SpriteID; } set { m_SpriteID = value; } }
        };

        // Generated MetaData
        [Serializable]
        internal class GeneratedSprites
        {
            [SerializeField]
            public Texture2D m_Texture2D;
            [SerializeField]
            public int m_PixelsPerUnit;
            [SerializeField]
            public SerializableSpriteImportData[] m_SpriteImportData;
        }

        [SerializeField]
        internal List<GeneratedSprites> m_GeneratedSpritesList;
    }
}
