using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using HelixToolkit.Wpf.SharpDX;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Windows;

namespace SparkClient.Views.UserControl.ViewportData.Helper;

public class VideoHelper
{
    public static  void CreateVideoFromPngList(List<PngBitmapEncoder> pngEncoders, string outputPath)
    {
        string tempDirectory = Path.Combine(System.Environment.CurrentDirectory, "PngFrames");
        Directory.CreateDirectory(tempDirectory);
        
        try
        {
            // Save each PNG frame to a temporary directory
            for (int i = 0; i < pngEncoders.Count; i++)
            {
                string framePath = Path.Combine(tempDirectory, $"frame_{i:D5}.png");
                using (FileStream fs = new FileStream(framePath, FileMode.Create))
                {
                    pngEncoders[i].Save(fs);
                }
            }

            // Use FFmpeg to create a video from the PNG frames
            string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ffmpeg.exe"); // Assuming ffmpeg.exe is in the same directory as the application
            if (!File.Exists(ffmpegPath))
            {
                throw new FileNotFoundException("FFmpeg executable not found.", ffmpegPath);
            }
            
            string framePattern = Path.Combine(tempDirectory, "frame_%05d.png").Replace("\\", "/"); // Replace backslashes with forward slashes for FFmpeg compatibility
            string arguments = $"-framerate 30 -i \"{framePattern}\" -vf \"scale=640:480\" -c:v libx264 -pix_fmt yuv420p \"{outputPath}\"";

            var processInfo = new System.Diagnostics.ProcessStartInfo
            {
                FileName = ffmpegPath,
                Arguments = arguments,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (var process = System.Diagnostics.Process.Start(processInfo))
            {
                string error = process.StandardError.ReadToEnd();
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    throw new Exception($"FFmpeg error: {error}");
                }
            }
            
            var dicName = Path.GetDirectoryName(outputPath);
            var fileName =Path.GetFileNameWithoutExtension(outputPath);
            Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(outputPath, fileName+".dat");
        }
        finally
        {
            // Clean up temporary frames
            Directory.Delete(tempDirectory, true);
        }
    }
    
     public static async Task CreateVideoFromPngListAsync(List<PngBitmapEncoder> pngEncoders, string outputPath)
    {
        string tempDirectory = Path.Combine(Environment.CurrentDirectory, "PngFrames");
        Directory.CreateDirectory(tempDirectory);
        await Task.Delay(1).ConfigureAwait(false);

        try
        {
            // Save each PNG frame to a temporary directory
            for (int i = 0; i < pngEncoders.Count; i++)
            {
                string framePath = Path.Combine(tempDirectory, $"frame_{i:D5}.png");

                await Task.Run(() =>
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        using (FileStream fs = new FileStream(framePath, FileMode.Create))
                        {
                            pngEncoders[i].Save(fs);
                        }
                    });
                }).ConfigureAwait(false);
            }

            // Use FFmpeg to create a video from the PNG frames
            string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ffmpeg.exe"); // Assuming ffmpeg.exe is in the same directory as the application
            if (!File.Exists(ffmpegPath))
            {
                // throw new FileNotFoundException("", ffmpegPath);
                MessageBox.Show("FFmpeg executable not found.", ffmpegPath);
            }

            string framePattern = Path.Combine(tempDirectory, "frame_%05d.png").Replace("\\", "/"); // Replace backslashes with forward slashes for FFmpeg compatibility
            string arguments = $"-framerate 30 -i \"{framePattern}\" -vf \"scale=640:480\" -c:v libx264 -pix_fmt yuv420p \"{outputPath}\"";

            var processInfo = new System.Diagnostics.ProcessStartInfo
            {
                FileName = ffmpegPath,
                Arguments = arguments,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (var process = System.Diagnostics.Process.Start(processInfo))
            {
                string error = await process.StandardError.ReadToEndAsync().ConfigureAwait(false);
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    throw new Exception($"FFmpeg error: {error}");
                }
            }

            // var dicName = Path.GetDirectoryName(outputPath);
            // var fileName = Path.GetFileNameWithoutExtension(outputPath);
            // Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(outputPath, fileName + ".dat");
        }
        finally
        {
            // Clean up temporary frames
            Directory.Delete(tempDirectory, true);
        }
    }
    
    public static void ConvertMp4ToDat(string inputFilePath, string outputFilePath)
    {
        string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ffmpeg.exe"); // Assuming ffmpeg.exe is in the same directory as the application
        if (!File.Exists(ffmpegPath))
        {
            throw new FileNotFoundException("FFmpeg executable not found.", ffmpegPath);
        }

        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = ffmpegPath,
            Arguments = $"-i \"{outputFilePath}\" \"{inputFilePath}\"",
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        
        File.Delete(outputFilePath);
       
    }

    public static async Task<List<PngBitmapEncoder>> StartGenerationAndRotation(Viewport3DX viewport)
    {

        
        var genPngTask = Task.Run(() => GenPng(viewport));
        
        var rotateModelTask = Task.Run(() => RotateModel());
        
        await Task.WhenAll(genPngTask, rotateModelTask);
        
        return genPngTask.Result;
    }
    
    public static List<PngBitmapEncoder> GenPng(Viewport3DX viewport)
    {
        List<PngBitmapEncoder> result = new List<PngBitmapEncoder>();

        for (int i = 0; i < 21000; i+=50)
        {
            // 使用 Dispatcher.Invoke 来确保 UI 操作在主线程中执行
            var encoder = Application.Current.Dispatcher.Invoke(() => CutPng(viewport));
            result.Add(encoder);
            Thread.Sleep(20); // 模拟处理过程
        }

        return result;
    }


    public static async void RotateModel()
    {
        await Application.Current.Dispatcher.InvokeAsync(() =>
        {
            var center = ViewportManager.ModelBounds.Center;
            var maxDimension = ViewportManager.ModelBounds.Size.Length();
            var distance = maxDimension *1.2; // 调整相机到模型的距离,保证视野范围内
            var camera = ViewportManager.GetViewport3D().Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera;
            camera.Position =  new Point3D(center.X, center.Y, center.Z + distance);  // 从前面看,Z轴正方向
            camera.Width = ViewportManager.calCameraWidth();
            camera.UpDirection = new Vector3D(0, -1, 0);    
            camera.LookDirection = new Vector3D(center.X -  camera.Position.X, center.Y -  camera.Position.Y, center.Z -  camera.Position.Z);
            ViewportHelperPro.RotateModel(new Vector3D(0,-1,0));
           
        });
        await Task.Delay(7000);
        await Application.Current.Dispatcher.InvokeAsync(() =>
        {
            ViewportHelperPro.RotateModel(new Vector3D(-1, 0, 0));
        });
        ViewportManager.DoubleClickSelect = !false;

    }

    public static PngBitmapEncoder CutPng(Viewport3DX viewport)
    {
        int width = (int)viewport.ActualWidth;
        int height = (int)viewport.ActualHeight;
        var renderTargetBitmap = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
        renderTargetBitmap.Render(viewport);
        var encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
        return encoder;
    }
}