// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED.
// THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License.
// LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License")
// YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License.
// YOU MAY OBTAIN A COPY OF THE LICENSE AT
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE
// DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND
// LIMITATIONS UNDER THE License.
// GITCODE: https://gitcode.com/AntdUI/AntdUI
// GITEE: https://gitee.com/AntdUI/AntdUI
// GITHUB: https://github.com/AntdUI/AntdUI
// CSDN: https://blog.csdn.net/v_132
// QQ: 17379620

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace AntdUI
{
    public class ImageData : IDisposable
    {
        byte[,] _red, _green, _blue, _alpha;
        bool _disposed = false;

        public byte[,] A
        {
            get => _alpha;
            set => _alpha = value;
        }
        public byte[,] B
        {
            get => _blue;
            set => _blue = value;
        }
        public byte[,] G
        {
            get => _green;
            set => _green = value;
        }
        public byte[,] R
        {
            get => _red;
            set => _red = value;
        }

        public ImageData Clone() => new ImageData
        {
            A = (byte[,])_alpha.Clone(),
            B = (byte[,])_blue.Clone(),
            G = (byte[,])_green.Clone(),
            R = (byte[,])_red.Clone()
        };

        public void FromBitmap(Bitmap srcBmp)
        {
            int w = srcBmp.Width;
            int h = srcBmp.Height;
            _alpha = new byte[w, h];
            _blue = new byte[w, h];
            _green = new byte[w, h];
            _red = new byte[w, h];
            BitmapData bmpData = srcBmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            IntPtr ptr = bmpData.Scan0;
            int bytes = bmpData.Stride * srcBmp.Height;
            byte[] rgbValues = new byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
            int offset = bmpData.Stride - w * 4;
            int index = 0;
            int y = 0, x;
            while (y < h)
            {
                x = 0;
                while (x < w)
                {
                    _blue[x, y] = rgbValues[index];
                    _green[x, y] = rgbValues[index + 1];
                    _red[x, y] = rgbValues[index + 2];
                    _alpha[x, y] = rgbValues[index + 3];
                    index += 4;
                    x++;
                }
                index += offset;
                y++;
            }
            srcBmp.UnlockBits(bmpData);
        }

        public Bitmap ToBitmap()
        {
            int width = 0, height = 0;
            if (_alpha != null)
            {
                width = Math.Max(width, _alpha.GetLength(0));
                height = Math.Max(height, _alpha.GetLength(1));
            }
            if (_blue != null)
            {
                width = Math.Max(width, _blue.GetLength(0));
                height = Math.Max(height, _blue.GetLength(1));
            }
            if (_green != null)
            {
                width = Math.Max(width, _green.GetLength(0));
                height = Math.Max(height, _green.GetLength(1));
            }
            if (_red != null)
            {
                width = Math.Max(width, _red.GetLength(0));
                height = Math.Max(height, _red.GetLength(1));
            }
            var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            int bytes = bmpData.Stride * bmp.Height;
            byte[] rgbValues = new byte[bytes];
            int offset = bmpData.Stride - width * 4;
            int i = 0;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    rgbValues[i] = checkArray(_blue, x, y) ? _blue[x, y] : (byte)0;
                    rgbValues[i + 1] = checkArray(_green, x, y) ? _green[x, y] : (byte)0;
                    rgbValues[i + 2] = checkArray(_red, x, y) ? _red[x, y] : (byte)0;
                    rgbValues[i + 3] = checkArray(_alpha, x, y) ? _alpha[x, y] : (byte)255;
                    i += 4;
                }
                i += offset;
            }
            System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, bmpData.Scan0, bytes);
            bmp.UnlockBits(bmpData);
            return bmp;
        }

        private static bool checkArray(byte[,] array, int x, int y)
        {
            if (array == null) return false;
            if (x < array.GetLength(0) && y < array.GetLength(1))
                return true;
            else return false;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _alpha = null;
                    _blue = null;
                    _green = null;
                    _red = null;
                }
                _disposed = true;
            }
        }
    }
}