using System;
using HandyControl.Controls;
using HandyControl.Tools;

namespace HandyControl.Data
{
    public class GifImageInfo
    {
        private const int PropertyTagFrameDelay = 0x5100;

        private int _frame;

        private readonly int[] _frameDelay;

        public int FrameCount { get; }

        internal GifImage Image { get; }

        public bool Animated { get; }

        public EventHandler FrameChangedHandler { get; set; }

        internal int FrameTimer { get; set; }

        public bool FrameDirty { get; private set; }

        public int Frame
        {
            get => _frame;
            set
            {
                if (_frame != value)
                {
                    if (value < 0 || value >= FrameCount)
                    {
                        throw new ArgumentException("InvalidFrame");
                    }

                    if (Animated)
                    {
                        _frame = value;
                        FrameDirty = true;

                        OnFrameChanged(EventArgs.Empty);
                    }
                }
            }
        }

        public GifImageInfo(GifImage image)
        {
            Image = image;
            Animated = ImageAnimator.CanAnimate(image);

            if (Animated)
            {
                FrameCount = image.GetFrameCount(GifFrameDimension.Time);

                var frameDelayItem = image.GetPropertyItem(PropertyTagFrameDelay);

                // If the image does not have a frame delay, we just return 0.                                     
                //
                if (frameDelayItem != null)
                {
                    // Convert the frame delay from byte[] to int
                    //
                    var values = frameDelayItem.Value;
                    _frameDelay = new int[FrameCount];
                    for (var i = 0; i < FrameCount; ++i)
                    {
                        _frameDelay[i] = values[i * 4] + 256 * values[i * 4 + 1] + 256 * 256 * values[i * 4 + 2] + 256 * 256 * 256 * values[i * 4 + 3];
                    }
                }
            }
            else
            {
                FrameCount = 1;
            }

            _frameDelay ??= new int[FrameCount];
        }

        public int FrameDelay(int frame) => _frameDelay[frame];

        internal void UpdateFrame()
        {
            if (FrameDirty)
            {
                Image.SelectActiveFrame(GifFrameDimension.Time, Frame);
                FrameDirty = false;
            }
        }

        protected void OnFrameChanged(EventArgs e) => FrameChangedHandler?.Invoke(Image, e);
    }
}
