using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HwComWrapperNETGui.UserControls
{
    public static class ConverterExtensions
    {
        /// <summary>
        ///     Gets the converted byte array equivalent to a given hex text.
        ///     The string is splitted by ' ' and '-'.
        ///     Examples: "00 0A 4B", "00-0A-4B" or "00 0a-4B"
        /// </summary>
        /// <param name="value"> the value as hex text.</param>
        /// <returns> the converted byte array equivalent to the given text; otherwise null</returns>
        public static byte[] GetByteArray(this string value)
        {
            var values = value.ToUpperInvariant().Split(new[] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries);
            var buffer = new byte[values.Length];
            var i = 0;
            foreach (var hexValue in values)
            {
                if (hexValue.Length > 2)
                {
                    return null;
                }

                byte result;
                if (!byte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out result))
                {
                    return null;
                }

                buffer[i] = result;
                i++;
            }

            return buffer;
        }

        /// <summary>
        ///     Gets the converted big endian byte array equivalent of the given value and byte length.
        /// </summary>
        /// <param name="value"> the value.</param>
        /// <param name="byteLength"> the byte length. 1, 2, 4 or 8.</param>
        /// <returns> the converted big endian byte array equivalent of the given value and byte length; otherwise null.</returns>
        public static byte[] GetByteArray(this decimal value, int byteLength)
        {
            try
            {
                switch (byteLength)
                {
                    case 1:
                        return new[] { Convert.ToByte(value) };
                    case 2: 
                        return BitConverter.IsLittleEndian
                            ? BitConverter.GetBytes(Convert.ToUInt16(value)).Reverse().ToArray()
                            : BitConverter.GetBytes(Convert.ToUInt16(value));

                    case 4:
                        return BitConverter.IsLittleEndian
                            ? BitConverter.GetBytes(Convert.ToUInt32(value)).Reverse().ToArray()
                            : BitConverter.GetBytes(Convert.ToUInt32(value));
                        
                    case 8:
                        return BitConverter.IsLittleEndian
                            ? BitConverter.GetBytes(Convert.ToUInt64(value)).Reverse().ToArray()
                            : BitConverter.GetBytes(Convert.ToUInt64(value));
                        
                }
            }
            catch (OverflowException)
            {
                MessageBox.Show(
                    "The value is too big for the given byte length. Please decrease value or increase byte length.",
                    "Value too big",
                    MessageBoxButtons.OK);
                return null;
            }
            
            MessageBox.Show(
                "The given Byte length value is not supported. Currently we only support 1, 2, 4 and 8 Bytes.",
                "Byte length value not supported",
                MessageBoxButtons.OK);
            return null;
        }

        /// <summary>
        ///     Gets the converted byte length equivalent of the given Bit length.
        /// </summary>
        /// <param name="bitLength"> the Bit length.</param>
        /// <returns> the converted byte length equivalent of the given Bit length; otherwise 0.</returns>
        public static ushort GetByteLength(this ushort bitLength)
        {
            if (bitLength <= 8)
            {
                return 1;
            }

            if (bitLength <= 16)
            {
                return 2;
            }

            if (bitLength <= 32)
            {
                return 4;
            }

            if (bitLength <= 64)
            {
                return 8;
            }

            MessageBox.Show(
                "The given Bit length value is not supported. Currently we only support a value less or equal 64.",
                "Bit length value too big",
                MessageBoxButtons.OK);

            return 0;
        }
    }
}
