using Microsoft.CSharp.RuntimeBinder;
//using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text.RegularExpressions;

public static class StaticHelper
{
   
    //判断是否为正整数
    public static bool IsInt(string inString)
    {
        Regex regex = new Regex("^[0-9]*[1-9][0-9]*$");
        return regex.IsMatch(inString.Trim());
    }
    /// <summary>
    /// 数值转换为byte数组 高位在前,低位在后
    /// </summary>
    /// <param name="number"></param>
    /// <param name="size"></param>
    /// <returns></returns>
    public static byte[] IntToBytes(this int number, int size = 2)
    {
        byte[] result = new byte[size];

        int temp = size;
        while (temp > 0)
        {
            result[size - temp] = (byte)(number >> ((temp - 1) * 8) & 0xff);

            temp--;
        }

        return result;
    }

    /// <summary>
    /// 字节数组转换为整数
    /// </summary>
    /// <param name="data">字节数组</param>
    /// <param name="HtL">true:数组序号低的在高位 false:数组序号低的在低位</param>
    /// <returns></returns>
    public static int BytesToInt(this byte[] data, bool HtL = true)
    {
        int res = 0;

        for (int i = 0; i < data.Length; i++)
        {
            int index = i;

            if (HtL)
            {
                index = data.Length - 1 - i;
            }

            res += data[index] << (8 * i);
        }

        return res;
    }

    /// <summary>
    /// 获取一个类指定的属性值
    /// </summary>
    /// <param name="info">object对象</param>
    /// <param name="field">属性名称</param>
    /// <returns></returns>
    public static object GetPropertyValue(object info, string field)
    {
        if (info == null) return null;
        Type t = info.GetType();
        IEnumerable<System.Reflection.PropertyInfo> property = from pi in t.GetProperties() where pi.Name.ToLower() == field.ToLower() select pi;
        return property.First().GetValue(info, null);
    }

    /// <summary>
    /// 将32位整形拆分为无符号16位整形
    /// </summary>
    /// <param name="num">需要拆分的32位整形</param>
    /// <param name="bitNum">拆分为16位整形的位数 1或者2</param>
    /// <param name="HtL">true:高位在前,低位在后;false:高位在后,低位在前</param>
    /// <returns></returns>
    public static List<ushort> ParseIntToUnsignShortList(this int num, int bitNum = 2, bool HtL = false)
    {
        if (bitNum == 2)
        {
            ushort high = (ushort)(num >> 16);
            ushort low = (ushort)num;

            if (HtL)
            {
                return new List<ushort>() { high, low };
            }
            else
            {
                return new List<ushort>() { low, high };
            }
        }
        else
        {
            if (num < 0)
            {
                num = ushort.MaxValue + 1 + num;
            }

            return new List<ushort>() { (ushort)num };
        }
    }

    /// <summary>
    /// 将32位整形数组拆分为无符号16位整形数组
    /// </summary>
    /// <param name="list">需要拆分的32位整形</param>
    /// <param name="bitNum">拆分为16位整形的位数 1或者2</param>
    /// <param name="HtL">true:高位在前,低位在后;false:高位在后,低位在前</param>
    /// <returns></returns>
    public static List<ushort> ParseIntToUnsignShortList(this List<int> list, int bitNum = 2, bool HtL = false)
    {
        return list.SelectMany(u => u.ParseIntToUnsignShortList(bitNum, HtL)).ToList();
    }

    /// <summary>
    /// 将ushort的集合转换为16位带符号整形
    /// </summary>
    /// <param name="numList"></param>
    /// <param name="bitNum">合并的位数 1或者2</param>
    /// <param name="HtL">true:高位在前,低位在后;false:高位在后,低位在前</param>
    /// <returns></returns>
    public static List<int> ParseUnsignShortListToInt(this List<int> numList, int bitNum = 2, bool HtL = false)
    {
        if (bitNum == 1)
        {
            return numList.ConvertAll(n =>
            {
                int num = n;
                if (num > short.MaxValue)
                {
                    num = num - ushort.MaxValue - 1;
                }

                return num;
            });
        }
        else
        {
            List<int> list = new List<int>();
            for (int i = 0; i < numList.Count; i += 2)
            {
                int high = HtL ? numList[i] : numList[i + 1];
                int low = HtL ? numList[i + 1] : numList[i];
                list.Add((high << 16) | low);
            }

            return list;
        }
    }

    //public static T DeepSerializeClone<T>(this T t)
    //{
    //    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(t));
    //}

    public static void DataFrom<T1, T2>(this T1 destT, T2 sourceT, List<string> exceptionProps = null) where T1 : class where T2 : class
    {
        if (sourceT == null)
        {
            destT = null;
            return;
        }

        PropertyInfo[] propDest = destT.GetType().GetProperties();//.Where(p => !(p.GetMethod.IsVirtual && !p.GetMethod.IsFinal)).ToArray();
        PropertyInfo[] propSource = sourceT.GetType().GetProperties();

        Array.ForEach(propDest, prop =>
        {
            if (exceptionProps == null || !exceptionProps.Contains(prop.Name))
            {
                if (prop.CanWrite)
                {
                    PropertyInfo propS = propSource.FirstOrDefault(p => p.Name == prop.Name);
                    if (propS != null && propS.CanRead)
                    {
                        prop.SetValue(destT, propS.GetValue(sourceT));
                    }
                }
            }
        });
    }

    public static Bitmap BitmapSerializeCopy(this Bitmap map)
    {
        Bitmap image = null;
        using (MemoryStream ms = new MemoryStream())
        {
            BinaryFormatter bf = new BinaryFormatter();
#if NET7_0_OR_GREATER
#pragma warning disable SYSLIB0011
#endif
            bf.Serialize(ms, map);
            ms.Seek(0, SeekOrigin.Begin);
            image = (Bitmap)bf.Deserialize(ms);
#if NET7_0_OR_GREATER
#pragma warning restore SYSLIB0011
#endif
            //ms.Close();
        }

        return image;
    }

    public static Bitmap DeepClone(this Bitmap bitmap)
    {
        Bitmap dstBitmap = null;
        using (MemoryStream mStream = new MemoryStream())
        {
            BinaryFormatter bf = new BinaryFormatter();
#if NET7_0_OR_GREATER
#pragma warning disable SYSLIB0011
#endif
            bf.Serialize(mStream, bitmap);
            //#pragma warning restore SYSLIB0011
            mStream.Seek(0, SeekOrigin.Begin);
            dstBitmap = (Bitmap)bf.Deserialize(mStream);
            mStream.Close();
#if NET7_0_OR_GREATER
#pragma warning restore SYSLIB0011
#endif
        }
        return dstBitmap;
    }
    //RtlMoveMemory
    [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
    public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
    [HandleProcessCorruptedStateExceptions]
    public static Bitmap CopyBitmap(this Bitmap source)
    {
        Bitmap clone = new Bitmap(source.Width, source.Height, source.PixelFormat);
        try
        {
            int PixelSize = Bitmap.GetPixelFormatSize(source.PixelFormat) / 8;
            if (PixelSize == 1)
            {
                ColorPalette cp = clone.Palette;
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(255, i, i, i);
                }
                clone.Palette = cp;
            }

            Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
            BitmapData sourceData = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
            BitmapData cloneData = clone.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
            if (source.Width % 4 == 0)
            {
                unsafe
                {
                    CopyMemory(cloneData.Scan0, sourceData.Scan0, (uint)(sourceData.Stride * sourceData.Height));
                }
            }
            else
            {
                Parallel.For(0, source.Height, h =>
                {
                    unsafe
                    {
                        CopyMemory(cloneData.Scan0 + h * sourceData.Stride, sourceData.Scan0 + h * sourceData.Stride, (uint)sourceData.Width);
                    }
                });
            }

            clone.UnlockBits(cloneData);
            source.UnlockBits(sourceData);

        }
        catch (Exception ex)
        {
            return clone;
        }

        return clone;
    }

    public static Bitmap BitmapDeepClone(Bitmap source)
    {
        Bitmap clone = new Bitmap(source.Width, source.Height, source.PixelFormat);

        try
        {
            int PixelSize = Bitmap.GetPixelFormatSize(source.PixelFormat) / 8;
            if (PixelSize == 1)
            {
                ColorPalette cp = clone.Palette;
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(255, i, i, i);
                }
                clone.Palette = cp;
            }
            Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
            BitmapData source_bitmap = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
            BitmapData destination_bitmap = clone.LockBits(rect, ImageLockMode.ReadWrite, clone.PixelFormat);

            int depth_width = source_bitmap.Width * PixelSize;

            unsafe
            {
                byte* source_ptr = (byte*)source_bitmap.Scan0;
                byte* destination_ptr = (byte*)destination_bitmap.Scan0;

                int offset = source_bitmap.Stride - depth_width;

                for (int i = 0; i < source_bitmap.Height; i++)
                {
                    for (int j = 0; j < depth_width; j++, source_ptr++, destination_ptr++)
                    {
                        *destination_ptr = *source_ptr;
                    }

                    source_ptr += offset;
                    destination_ptr += offset;
                }
            }

            source.UnlockBits(source_bitmap);
            clone.UnlockBits(destination_bitmap);
        }
        catch (Exception ex)
        {

        }
        return clone;
    }



    public static Bitmap HConnectBitmap(this Bitmap map1, Bitmap map2)
    {
        Bitmap connectImage = null;
        if (map1 == null || map2 == null)
            return null;
        //横向拼接
        int width = map1.Width + map2.Width;
        //高度不变
        int height = Math.Max(map1.Height, map2.Height);
        connectImage = new Bitmap(width, height);
        using (Graphics graph = Graphics.FromImage(connectImage))
        {
            graph.DrawImage(connectImage, width, height);
            graph.Clear(System.Drawing.Color.White);
            graph.DrawImage(map1, 0, 0);
            graph.DrawImage(map2, map1.Width, 0);
        }
        return connectImage;
    }

    public static IntPtr FloatToIntptr(float[] bytes)
    {
        GCHandle hObject = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        return hObject.AddrOfPinnedObject();
    }

    // 将Btimap类转换为byte[]类函数
    public static byte[] GetBGRValues(Bitmap bmp, out int stride)
    {
        var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        var bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
        stride = bmpData.Stride;
        var rowBytes = bmpData.Width * Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
        var imgBytes = bmp.Height * rowBytes;
        byte[] rgbValues = new byte[imgBytes];
        IntPtr ptr = bmpData.Scan0;
        for (var i = 0; i < bmp.Height; i++)
        {
            Marshal.Copy(ptr, rgbValues, i * rowBytes, rowBytes);
            ptr += bmpData.Stride;
        }
        bmp.UnlockBits(bmpData);
        return rgbValues;
    }
    /// <summary>
    /// 缺陷灰度图转彩色图像函数
    /// </summary>
    /// <param name="src">灰度图</param>
    /// <returns>返回构造的伪彩色图像</returns>
    public static Bitmap GrayMapToColorMap(this Bitmap src, Dictionary<int, Color> indexColorDict = null)
    {
        try
        {
            //Stopwatch sw = new Stopwatch();
            //sw.Start();

            Bitmap dest = new Bitmap(src.Width, src.Height, PixelFormat.Format32bppArgb);

            int destHeight = dest.Height;
            int destWidth = dest.Width;

            Rectangle rect = new Rectangle(0, 0, destWidth, destHeight);
            BitmapData bmpDataDest = dest.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            BitmapData bmpDataSrc = src.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
            int strideDest = bmpDataDest.Stride;

            int strideSrc = bmpDataSrc.Stride;
            unsafe
            {
                byte* pDest = (byte*)bmpDataDest.Scan0.ToPointer();
                byte* pSrc = (byte*)bmpDataSrc.Scan0.ToPointer();

                Parallel.For(0, destHeight, y =>
                {
                    Parallel.For(0, destWidth, x =>
                    {
                        int pixel = pSrc[y * strideSrc + x];
                        int startIndex = y * strideDest + x * 4;
                        if (pixel >= 0 && pixel <= 63)
                        {
                            Color color = Color.Red;
                            if (indexColorDict != null && indexColorDict.ContainsKey(pixel))
                            {
                                color = indexColorDict[pixel];
                            }

                            byte R = color.R;
                            byte G = color.G;
                            byte B = color.B;

                            pDest[startIndex] = B;
                            pDest[startIndex + 1] = G;
                            pDest[startIndex + 2] = R;
                            pDest[startIndex + 3] = 100;
                        }
                        else
                        {
                            pDest[startIndex] = 255;
                            pDest[startIndex + 1] = 255;
                            pDest[startIndex + 2] = 255;
                            pDest[startIndex + 3] = 0;
                        }
                    });
                });
            }
            dest.UnlockBits(bmpDataDest);
            src.UnlockBits(bmpDataSrc);

            //sw.Stop();
            //Console.WriteLine($"转换耗时:{sw.ElapsedMilliseconds}");

            return dest;
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable<T>
    {
        List<T> sortedList = collection.OrderByDescending(x => x).ToList();//这里用降序 
        for (int i = 0; i < sortedList.Count(); i++)
        {
            collection.Move(collection.IndexOf(sortedList[i]), i);
        }
    }

    /// <summary>
    /// 获得字符串中开始和结束字符串中间的值
    /// </summary>
    /// <param name="sourse"></param>
    /// <param name="startstr"></param>
    /// <param name="endstr"></param>
    /// <returns></returns>
    public static string GetMidString(string sourse, string startstr, string endstr)
    {
        string result = string.Empty;
        int startindex, endindex;
        try
        {
            startindex = sourse.IndexOf(startstr);
            if (startindex == -1)
                return result;
            string tmpstr = sourse.Substring(startindex + startstr.Length);
            endindex = tmpstr.IndexOf(endstr);
            if (endindex == -1)
                return result;
            result = tmpstr.Remove(endindex);
        }
        catch (Exception ex)
        {
            return "";
        }
        return result;
    }

    /// <summary>
    /// 获得字符串中开始和结束字符串中间的值
    /// </summary>
    /// <param name="t">字符串</param>
    /// <param name="k">开始</param>
    /// <param name="j">结束</param>
    /// <returns></returns> 
    private static string GetMidString2(string sourse, string startstr, string endstr) //截取指定文本,和易语言的取文本中间差不多
    {
        try //异常捕捉
        {
            var kn = sourse.IndexOf(startstr, StringComparison.Ordinal) + startstr.Length;
            var jn = sourse.IndexOf(endstr, kn, StringComparison.Ordinal);
            return sourse.Substring(kn, jn - kn);
        }
        catch //如果发现未知的错误,比如上面的代码出错了,就执行下面这句代码
        {
            return ""; //返回空
        }

    }

    // 布尔类型转换为整型
    public static int ToInt(this object obj)
    {
        if (Convert.ToBoolean(obj) == true)
            return 1;
        else
            return 0;
    }

    // 整型转换为布尔类型
    public static bool ToBool(this object obj)
    {
        if (Convert.ToInt32(obj) == 1)
            return true;
        else
            return false;
    }

    public static object GetProperty(this object o, string member)
    {
        if (o == null) throw new ArgumentNullException("o");
        if (member == null) throw new ArgumentNullException("member");
        Type scope = o.GetType();
        IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
        if (provider != null)
        {
            ParameterExpression param = Expression.Parameter(typeof(object));
            DynamicMetaObject mobj = provider.GetMetaObject(param);
            GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) });
            DynamicMetaObject ret = mobj.BindGetMember(binder);
            BlockExpression final = Expression.Block(
                Expression.Label(CallSiteBinder.UpdateLabel),
                ret.Expression
            );
            LambdaExpression lambda = Expression.Lambda(final, param);
            Delegate del = lambda.Compile();
            return del.DynamicInvoke(o);
        }
        else
        {
            return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
        }
    }

    #region 检测文件状态及操作方式选择
    [DllImport("kernel32.dll")]
    private static extern IntPtr _lopen(string lpPathName, int iReadWrite);
    [DllImport("kernel32.dll")]
    private static extern bool CloseHandle(IntPtr hObject);
    private const int OF_READWRITE = 2;
    private const int OF_SHARE_DENY_NONE = 0x40;
    private static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
    /// <summary>
    /// 检测文件是否只读或被使用
    /// </summary>
    /// <param name="FileNames">要检测的文件</param>
    /// <returns>true可用,false在用或只读</returns>
    public static bool CheckFilesCanUse(string fileName)
    {
        if (!File.Exists(fileName))
            return true;//文件不存在
        if ((File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            return false;       //文件只读
        IntPtr vHandle = _lopen(fileName, OF_READWRITE | OF_SHARE_DENY_NONE);
        if (vHandle == HFILE_ERROR)
        {
            CloseHandle(vHandle);
            return false;       //文件被占用
        }

        CloseHandle(vHandle);   //文件没被占用
        return true;
    }
    #endregion

    /// <summary>
    /// 获取指定文件夹下所有的文件名称
    /// </summary>
    /// <param name="folderName">指定文件夹名称,绝对路径</param>
    /// <param name="fileFilter">文件类型过滤,根据文件后缀名,如:*,*.txt,*.xls</param>
    /// <param name="isContainSubFolder">是否包含子文件夹</param>
    /// <returns>ArrayList数组,为所有需要的文件路径名称</returns>
    public static List<FileInfo> GetAllFilesByFolder(string folderName, string fileFilter, bool isContainSubFolder = false)
    {
        List<FileInfo> resList = new List<FileInfo>();
        try
        {
            DirectoryInfo currDir = new DirectoryInfo(folderName);//当前目录
            FileInfo[] currFiles = currDir.GetFiles(fileFilter);//当前目录文件
            foreach (FileInfo file in currFiles)
            {
                if (fileFilter.ToLower().IndexOf(file.Extension.ToLower()) >= 0)
                {
                    resList.Add(file);
                }
            }
            if (isContainSubFolder)
            {
                string[] subFolders = Directory.GetDirectories(folderName);
                foreach (string subFolder in subFolders)
                {
                    resList.AddRange(GetAllFilesByFolder(subFolder, fileFilter));//递归   
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return resList;
    }

    /// <summary>
    /// 获取指定文件夹下所有的文件名称,不过滤文件类型
    /// </summary>
    /// <param name="folderName">指定文件夹名称,绝对路径</param>
    /// <param name="isContainSubFolder">是否包含子文件夹</param>
    /// <returns>ArrayList数组,为所有需要的文件路径名称</returns>
    public static List<FileInfo> GetAllFilesByFolder(string folderName, bool isContainSubFolder)
    {
        return GetAllFilesByFolder(folderName, "*", isContainSubFolder);
    }
}

public class Compare<T, C> : IEqualityComparer<T>
    {
        private Func<T, C> _getField;
        public Compare(Func<T, C> getfield)
        {
            _getField = getfield;
        }
        public bool Equals(T x, T y)
        {
            return EqualityComparer<C>.Default.Equals(_getField(x), _getField(y));
        }
        public int GetHashCode(T obj)
        {
            return EqualityComparer<C>.Default.GetHashCode(_getField(obj));
        }
    }

    public static class ObjectExtensions
    {
        public static IEnumerable<T> DistinctBy<T, C>(this IEnumerable<T> source, Func<T, C> getfield)
        {
            return source.Distinct(new Compare<T, C>(getfield));
        }

        public static IQueryable<T> DistinctBy<T, C>(this IQueryable<T> source, Func<T, C> getfield)
        {
            return source.Distinct(new Compare<T, C>(getfield));
        }
    }