using SharpDX.WIC;
using SharpDX.Direct2D1;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using System.IO;
using SharpDX.IO;

namespace VIZ.Framework.Common
{
    /// <summary>
    /// WIC图片辅助类
    /// </summary>
    public static class WicBitmapHelper
    {
        /// <summary>
        /// 渲染至WicBitmap
        /// </summary>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="render">渲染方法</param>
        /// <param name="plugins">渲染插件</param>
        /// <returns>WicBitmap</returns>
        public static SharpDX.WIC.Bitmap RenderToBitmap(int width, int height, Action<VideoRenderContext> render, List<string> plugins = null)
        {
            ImagingFactory wicFactory = new ImagingFactory();
            SharpDX.Direct2D1.Factory d2dFactory = new SharpDX.Direct2D1.Factory();
            SharpDX.WIC.Bitmap wicBitmap = new SharpDX.WIC.Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);

            RenderTargetProperties renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new SharpDX.Direct2D1.PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);

            WicRenderTarget d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties);

            d2dRenderTarget.BeginDraw();

            VideoRenderContext context = new VideoRenderContext();
            context.Mode = VideoRenderMode.Image;
            context.Target = d2dRenderTarget;
            context.RenderImagePlugins = plugins;

            render.Invoke(context);

            d2dRenderTarget.EndDraw();

            d2dRenderTarget.Dispose();
            d2dFactory.Dispose();
            wicFactory.Dispose();

            return wicBitmap;
        }

        /// <summary>
        /// 渲染至文件
        /// </summary>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="fileName">文件名</param>
        /// <param name="format">图片格式</param>
        /// <param name="render">渲染行为</param>
        public static void RenderToFile(int width, int height, string fileName, WicBitmapFormat format, Action<WicRenderTarget> render)
        {
            ImagingFactory wicFactory = new ImagingFactory();
            SharpDX.Direct2D1.Factory d2dFactory = new SharpDX.Direct2D1.Factory();
            SharpDX.WIC.Bitmap wicBitmap = new SharpDX.WIC.Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);

            RenderTargetProperties renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new SharpDX.Direct2D1.PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);

            WicRenderTarget d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties);

            d2dRenderTarget.BeginDraw();

            render.Invoke(d2dRenderTarget);

            d2dRenderTarget.EndDraw();

            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }

            WICStream stream = new WICStream(wicFactory, fileName, NativeFileAccess.Write);

            BitmapEncoder encoder = GetBitmapFrameEncoder(wicFactory, format);
            encoder.Initialize(stream);

            // Create a Frame encoder
            BitmapFrameEncode bitmapFrameEncode = new BitmapFrameEncode(encoder);
            bitmapFrameEncode.Initialize();
            bitmapFrameEncode.SetSize(width, height);
            var pixelFormatGuid = SharpDX.WIC.PixelFormat.FormatDontCare;
            bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid);
            bitmapFrameEncode.WriteSource(wicBitmap);

            bitmapFrameEncode.Commit();
            encoder.Commit();

            bitmapFrameEncode.Dispose();
            encoder.Dispose();
            stream.Dispose();

            d2dRenderTarget.Dispose();
            wicBitmap.Dispose();
            d2dFactory.Dispose();
            wicFactory.Dispose();
        }

        /// <summary>
        /// 获取保存图片格式
        /// </summary>
        /// <param name="factory">图片工厂</param>
        /// <param name="format">图片格式</param>
        /// <returns>图片格式</returns>
        private static BitmapEncoder GetBitmapFrameEncoder(ImagingFactory factory, WicBitmapFormat format)
        {
            switch (format)
            {
                case WicBitmapFormat.JPG:
                    return new JpegBitmapEncoder(factory);
                default:
                    return null;
            }
        }
    }
}
