using DirectShowLib;
using System;
using System.Runtime.InteropServices;

namespace DualScreenDemo.Services
{
    public class MediaServicePrimary : Video
    {
        IGraphBuilder graphBuilder;
        IBaseFilter lavSplitter;
        IBaseFilter lavVideoDecoder;
        IBaseFilter videoRenderer;
        IVideoWindow videoWindow;
        IMediaControl mediaControl;
        IBaseFilter sourceFilter;


        public MediaServicePrimary() { }

        public int Run()
        {
            if (mediaControl != null)
                return mediaControl.Run();
            else
                return 0;
        }
        public int Stop()
        {
            if (mediaControl != null)
                return mediaControl.Stop();
            else
                return 0;

        }
        public int Pause()
        {
            if (mediaControl != null)
                return mediaControl.Pause();
            else
                return 0;
        }
        public void VideoPlayerFormClosing()
        {
            if (videoWindow != null)
            {
                videoWindow.put_Visible(OABool.False);
                videoWindow.put_Owner(IntPtr.Zero);
                Marshal.ReleaseComObject(videoWindow);
                videoWindow = null;
            }
        }

        public void StopAndReleaseResources()
        {
            if (mediaControl != null)
            {
                mediaControl.Stop();
                SafeRelease(ref mediaControl);
            }
            SafeRelease(ref videoWindow);
            SafeRelease(ref videoRenderer);
            SafeRelease(ref sourceFilter);
            SafeRelease(ref lavVideoDecoder);
            SafeRelease(ref lavSplitter);
            SafeRelease(ref graphBuilder);
        }

        public void RenderMediaFile(string filePath, nint Handle, int Width, int Height)
        {
            StopAndReleaseResources();
            if (videoWindow != null) videoWindow.put_Visible(OABool.False);

            int hr;
            graphBuilder = (IGraphBuilder)new FilterGraph();
            if (graphBuilder == null)
                throw new Exception("Failed to create FilterGraph for primary monitor.");

            graphBuilder.AddSourceFilter(filePath, "Source", out sourceFilter);
            try
            {
                lavSplitter = AddFilterByClsid(graphBuilder, "LAV Splitter", Clsid.LAVSplitter);
                lavVideoDecoder = AddFilterByClsid(graphBuilder, "LAV Video Decoder", Clsid.LAVVideoDecoder);
                videoRenderer = AddFilterByClsid(graphBuilder, "Primary Video Renderer", Clsid.VideoRenderer);
                hr = graphBuilder.AddFilter(videoRenderer, "Primary Video Renderer");
                DsError.ThrowExceptionForHR(hr);

                mediaControl = (IMediaControl)graphBuilder;
                if (mediaControl == null)
                {
                    Console.WriteLine("Failed to get Media Control for primary monitor.");
                    return;
                }
                hr = ConnectFilters(graphBuilder, sourceFilter, "Output", lavSplitter, "Input");
                DsError.ThrowExceptionForHR(hr);
                hr = ConnectFilters(graphBuilder, lavSplitter, "Video", lavVideoDecoder, "Input");
                DsError.ThrowExceptionForHR(hr);
                hr = ConnectFilters(graphBuilder, lavVideoDecoder, "Output", videoRenderer, "VMR Input0");
                DsError.ThrowExceptionForHR(hr);

                try
                {

                    IVideoWindow videoWindow = (IVideoWindow)videoRenderer;
                    videoWindow.put_Owner(Handle);
                    videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);

                    // ⬅ 左上角對齊（固定從 0,0 開始）
                    videoWindow.SetWindowPosition(0, 0, Width, Height);

                    videoWindow.put_Visible(OABool.True);

                    // Console.WriteLine("Video window configured successfully.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(String.Format("Error syncing to primary monitor: {0}", ex.Message));
                    MessageBox.Show(String.Format("Error syncing to primary monitor: {0}", ex.Message));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error initializing graph builder for primary monitor: " + ex.Message);
            }
        }
        
    }
}