using System;
using System.Runtime.InteropServices;
using HandyControl.Tools.Interop;

namespace HandyControl.Data
{
    [StructLayout(LayoutKind.Sequential)]
    public class GifPropertyItemInternal : IDisposable
    {
        public int id;
        public int len;
        public short type;
        public IntPtr value = IntPtr.Zero;

        internal GifPropertyItemInternal()
        {
        }

        public byte[] Value
        {
            get
            {
                if (len == 0)
                    return null;

                var bytes = new byte[len];

                Marshal.Copy(value,
                    bytes,
                    0,
                    len);
                return bytes;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        ~GifPropertyItemInternal()
        {
            Dispose(false);
        }

        private void Dispose(bool disposing)
        {
            if (value != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(value);
                value = IntPtr.Zero;
            }

            if (disposing)
                GC.SuppressFinalize(this);
        }

        internal static GifPropertyItemInternal ConvertFromPropertyItem(GifPropertyItem propItem)
        {
            var propItemInternal = new GifPropertyItemInternal
            {
                id = propItem.Id,
                len = 0,
                type = propItem.Type
            };

            var propItemValue = propItem.Value;
            if (propItemValue != null)
            {
                var length = propItemValue.Length;
                propItemInternal.len = length;
                propItemInternal.value = Marshal.AllocHGlobal(length);
                Marshal.Copy(propItemValue, 0, propItemInternal.value, length);
            }

            return propItemInternal;
        }

        internal static GifPropertyItem[] ConvertFromMemory(IntPtr propdata, int count)
        {
            var props = new GifPropertyItem[count];

            for (var i = 0; i < count; i++)
            {
                GifPropertyItemInternal propcopy = null;
                try
                {
                    propcopy = (GifPropertyItemInternal) InteropMethods.PtrToStructure(propdata,
                        typeof(GifPropertyItemInternal));

                    props[i] = new GifPropertyItem
                    {
                        Id = propcopy.id,
                        Len = propcopy.len,
                        Type = propcopy.type,
                        Value = propcopy.Value
                    };

                    // this calls Marshal.Copy and creates a copy of the original memory into a byte array.

                    propcopy.value = IntPtr.Zero; // we dont actually own this memory so dont free it.
                }
                finally
                {
                    propcopy?.Dispose();
                }

                propdata = (IntPtr) ((long) propdata + Marshal.SizeOf(typeof(GifPropertyItemInternal)));
            }

            return props;
        }
    }
}
