using System;
using System.IO;
using UnityEngine;
namespace UnityEditor.U2D.Aseprite
{
    /// 
    /// Aseprite Chunk Types.
    /// 
    public enum ChunkTypes
    {
        /// Default type
        None = 0,
        /// Old palette data
        OldPalette = 0x0004,
        /// Second old palette data - Not in use
        OldPalette2 = 0x0011,
        /// Layer data
        Layer = 0x2004,
        /// Cell data
        Cell = 0x2005,
        /// Extra cell data - Not in use
        CellExtra = 0x2006,
        /// Color profile data
        ColorProfile = 0x2007,
        /// External files data - Not in use
        ExternalFiles = 0x2008,
        /// Mask data - Not in use
        Mask = 0x2016,
        /// Path data - Not in use
        Path = 0x2017,
        /// Tag data
        Tags = 0x2018,
        /// Palette data
        Palette = 0x2019,
        /// User data
        UserData = 0x2020,
        /// Slice data - Not in use
        Slice = 0x2022,
        /// Tile set data - Not in use
        Tileset = 0x2023
    }
    /// 
    /// The header of each chunk.
    /// 
    public class ChunkHeader
    {
        /// 
        /// The stride of the chunk header in bytes.
        /// 
        public const int stride = 6;
        /// 
        /// The size of the chunk in bytes.
        /// 
        public uint chunkSize { get; private set; }
        /// 
        /// The type of the chunk.
        /// 
        public ChunkTypes chunkType { get; private set; }
        internal void Read(BinaryReader reader)
        {
            chunkSize = reader.ReadUInt32();
            chunkType = (ChunkTypes)reader.ReadUInt16();
        }
    }
    /// 
    /// Base class for all chunks.
    /// 
    public abstract class BaseChunk : IDisposable
    {
        /// 
        /// The type of the chunk.
        /// 
        public virtual ChunkTypes chunkType => ChunkTypes.None;
        /// 
        /// The size of the chunk in bytes.
        /// 
        protected readonly uint m_ChunkSize;
        /// 
        /// Constructor.
        /// 
        /// The size of the chunk in bytes.
        protected BaseChunk(uint chunkSize)
        {
            m_ChunkSize = chunkSize;
        }
        internal bool Read(BinaryReader reader)
        {
            var bytes = reader.ReadBytes((int)m_ChunkSize - ChunkHeader.stride);
            using var memoryStream = new MemoryStream(bytes);
            using var chunkReader = new BinaryReader(memoryStream);
            try
            {
                InternalRead(chunkReader);
            }
            catch (Exception e)
            {
                Debug.LogError($"Failed to read a chunk of type: {chunkType}. Skipping the chunk. \nException: {e}");
                return false;
            }
            return true;
        }
        /// 
        /// Implement this method to read the chunk data.
        /// 
        /// The active binary reader of the file.
        protected abstract void InternalRead(BinaryReader reader);
        /// 
        /// Implement this method to dispose of the chunk data.
        /// 
        public virtual void Dispose() { }
    }
}