using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace Install.Core.Common
{
    public static class IconExt
    {
        //details: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648075(v=vs.85).aspx
        //Creates an array of handles to icons that are extracted from a specified file.
        //This function extracts from executable (.exe), DLL (.dll), icon (.ico), cursor (.cur), animated cursor (.ani), and bitmap (.bmp) files. 
        //Extractions from Windows 3.x 16-bit executables (.exe or .dll) are also supported.
        [DllImport("User32.dll")]
        public static extern int PrivateExtractIcons(
            string lpszFile, //file name
            int nIconIndex,  //The zero-based index of the first icon to extract.
            int cxIcon,      //The horizontal icon size wanted.
            int cyIcon,      //The vertical icon size wanted.
            IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
            int[] piconid,   //(out) A pointer to a returned resource identifier.
            int nIcons,      //The number of icons to extract from the file. Only valid when *.exe and *.dll
            int flags        //Specifies flags that control this function.
        );

        //details:https://msdn.microsoft.com/en-us/library/windows/desktop/ms648063(v=vs.85).aspx
        //Destroys an icon and frees any memory the icon occupied.
        [DllImport("User32.dll")]
        public static extern bool DestroyIcon(
            IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
        );

        //public static int SaveIcon(string exePath, string outFolder) 
        //{
        //    //指定存放图标的文件夹
        //    if (!Directory.Exists(outFolder)) Directory.CreateDirectory(outFolder);

            
        //    //选中文件中的图标总数
        //    var iconTotalCount = PrivateExtractIcons(exePath, 0, 0, 0, null, null, 0, 0);

        //    //用于接收获取到的图标指针
        //    IntPtr[] hIcons = new IntPtr[iconTotalCount];
        //    //对应的图标id
        //    int[] ids = new int[iconTotalCount];
        //    //成功获取到的图标个数
        //    var successCount = PrivateExtractIcons(exePath, 0, 256, 256, hIcons, ids, iconTotalCount, 0);

        //    string filename = Path.GetFileNameWithoutExtension(exePath);
        //    //遍历并保存图标
        //    for (var i = 0; i < successCount; i++)
        //    {
        //        //指针为空，跳过
        //        if (hIcons[i] == IntPtr.Zero) continue;

        //        using (var ico = Icon.FromHandle(hIcons[i]))
        //        {
        //            using (var myIcon = ico.ToBitmap())
        //            {
        //                string iconpath = $@"{outFolder}\{filename}.png";
        //                if (i == 0)
        //                    iconpath = $@"{outFolder}\{filename}.png";
        //                else
        //                    iconpath = $@"{outFolder}\{filename}{ids[i]:000} .png";

        //                if (File.Exists(iconpath))
        //                    File.Delete(iconpath);
                        
        //                myIcon.Save(iconpath, ImageFormat.Png);
        //            }
        //        }
        //        //内存回收
        //        DestroyIcon(hIcons[i]);
        //    }
        //    return successCount;
        //}

        public static bool SaveIcon(string exePath, string outFolder)
        {
            //指定存放图标的文件夹
            if (!Directory.Exists(outFolder)) Directory.CreateDirectory(outFolder);
            string filename = Path.GetFileNameWithoutExtension(exePath);
            string iconpath = $@"{outFolder}\{filename}.png";
            if (File.Exists(iconpath))
                return true;


            //选中文件中的图标总数
            var iconTotalCount = PrivateExtractIcons(exePath, 0, 0, 0, null, null, 0, 0);

            if (iconTotalCount <= 0)
                return false;

            iconTotalCount = 1;
            //用于接收获取到的图标指针
            IntPtr[] hIcons = new IntPtr[iconTotalCount];
            //对应的图标id
            int[] ids = new int[iconTotalCount];
            //成功获取到的图标个数
            var successCount = PrivateExtractIcons(exePath, 0, 256, 256, hIcons, ids, iconTotalCount, 0);
            if (successCount != iconTotalCount)
                return false;

            //遍历并保存图标

            //指针为空，跳过
            if (hIcons[0] == IntPtr.Zero) return false;

            using (var ico = Icon.FromHandle(hIcons[0]))
            {
                using (Bitmap myIcon = ico.ToBitmap())
                {
                    myIcon.Save(iconpath, ImageFormat.Png);
                }
            }
            //内存回收
            DestroyIcon(hIcons[0]);
            return true;
        }

        public static BitmapSource GetIcon(string exePath)
        {
            //选中文件中的图标总数
            var iconTotalCount = PrivateExtractIcons(exePath, 0, 0, 0, null, null, 0, 0);

            if (iconTotalCount <= 0)
                return null;

            iconTotalCount = 1;
            //用于接收获取到的图标指针
            IntPtr[] hIcons = new IntPtr[iconTotalCount];
            //对应的图标id
            int[] ids = new int[iconTotalCount];
            //成功获取到的图标个数
            var successCount = PrivateExtractIcons(exePath, 0, 256, 256, hIcons, ids, iconTotalCount, 0);
            if (successCount != iconTotalCount)
                return null;

            //遍历并保存图标

            //指针为空，跳过
            if (hIcons[0] == IntPtr.Zero) return null;

            using (var ico = Icon.FromHandle(hIcons[0]))
            {
                using (Bitmap myIcon = ico.ToBitmap())
                {
                    var bitmapSource =myIcon.CreateBitmapSource();
                    //内存回收
                    DestroyIcon(hIcons[0]);
                    return bitmapSource;
                }
            }
        }
    }
}
