using System.IO; // For StreamWriter
using System.Runtime.InteropServices;
using System.Windows.Media;
using DirectShowLib;
using DBObj;
using OverlayFormObj;
using DualScreenDemo.Services;
namespace DualScreenDemo
{
    public class VideoPlayerForm : Form
    {
        #region 防止閃屏

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }
        #endregion


        // 单例实例
        public static VideoPlayerForm Instance { get; private set; }

        // 导入user32.dll API
        [DllImport("user32.dll")]
        static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        // Windows API 函數
        [DllImport("user32.dll")]
        static extern IntPtr GetDesktopWindow();

        [DllImport("user32.dll")]
        static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);

        [DllImport("user32.dll")]
        static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

        // MONITORINFO 結構
        [StructLayout(LayoutKind.Sequential)]
        struct MONITORINFO
        {
            public int cbSize;
            public RECT rcMonitor;
            public RECT rcWork;
            public uint dwFlags;
        }

        // RECT 結構
        [StructLayout(LayoutKind.Sequential)]
        struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        private const int GWL_EXSTYLE = -20;
        private const int WS_EX_TOPMOST = 0x00000008;
        private const uint SWP_NOZORDER = 0x0004;
        private MediaServicePrimary primary = new MediaServicePrimary();
        private MediaService secondary = new MediaService();

        public static OverlayForm overlayForm;
        public bool isMuted = false;
        public int previousVolume = 0;
        public bool isPaused = false;
        private bool isSyncToPrimaryMonitor = false;

        public bool IsSyncToPrimaryMonitor
        {
            get { return isSyncToPrimaryMonitor; }
            set { isSyncToPrimaryMonitor = value; }
        }

        private static Screen secondMonitor;
        private int newWidth;
        private int newHeight;

        public VideoPlayerForm()
        {
            Lold();
            Instance = this;
            // this.DoubleBuffered = true;
            this.Load += VideoPlayerForm_Load;
            this.Shown += VideoPlayerForm_Shown;
            this.FormClosing += VideoPlayerForm_FormClosing;
            InitializeOverlayForm(secondMonitor);
            BringOverlayToFront();
            HttpServer.OnDisplayBarrage += DisplayBarrageOnOverlay;
            MonitorMediaEvents();
        }
        void Lold(){
            int designWidth = 1620;
            int designHeight = 1080;

            int actualWidth = PrimaryForm.Instance.primaryScreenPanel.Width;
            int actualHeight = PrimaryForm.Instance.primaryScreenPanel.Height;

            // 等比例縮放（不會超出，fit）
            float scaleX = (float)actualWidth / designWidth;
            float scaleY = (float)actualHeight / designHeight;
            float scale = Math.Min(scaleX, scaleY);

            // 計算縮放後的尺寸（但起點仍是 0,0）
            newWidth = (int)(designWidth * scale);
            newHeight = (int)(designHeight * scale);

            // trash location with trash flexible of screen size.
            if (actualWidth == 1024)
            {
                newWidth = (int)(newWidth * 0.84f);
            }
            else if (actualWidth == 1440)
            {
                newWidth = (int)(newWidth * 0.9f);
            }
        }

        private void VideoPlayerForm_Load(object sender, EventArgs e)
        {
            secondMonitor = ScreenHelper.GetSecondMonitor();
            if (secondMonitor != null)
            {
                this.FormBorderStyle = FormBorderStyle.None; // 设置窗体没有边框
                this.StartPosition = FormStartPosition.Manual;
                this.Location = secondMonitor.Bounds.Location;
                this.Size = secondMonitor.Bounds.Size;
                // this.DoubleBuffered = true;
            }
            Screen screen = Screen.FromHandle(this.Handle);
        }

        private void VideoPlayerForm_Shown(object sender, EventArgs e)
        {
            int hr = CoInitializeEx(IntPtr.Zero, COINIT.APARTMENTTHREADED);
            if (hr < 0)
            {
                Console.WriteLine("Failed to initialize COM library.");
                return;
            }
            else
            { 
                PlayNextSong();
            }
        }

        private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            primary.VideoPlayerFormClosing();
            secondary.VideoPlayerFormClosing();
            // 清理COM
            CoUninitialize();
        }

        // COM API函数声明
        [DllImport("ole32.dll")]
        private static extern int CoInitializeEx(IntPtr pvReserved, COINIT dwCoInit);

        [DllImport("ole32.dll")]
        private static extern void CoUninitialize();

        // CoInitializeEx() 可以选择的参数
        private enum COINIT : int
        {
            APARTMENTTHREADED = 0x2,
            MULTITHREADED = 0x0
        }
        
        // 同步畫面事件
        public void SyncToPrimaryMonitor()
        {
            PrimaryForm.Instance.primaryScreenPanel.Visible = true;
            PrimaryForm.Instance.primaryScreenPanel.BringToFront();
            PrimaryForm.Instance.syncServiceBellButton.Visible = true;
            PrimaryForm.Instance.syncServiceBellButton.BringToFront();
            PrimaryForm.Instance.syncCutSongButton.Visible = true;
            PrimaryForm.Instance.syncCutSongButton.BringToFront();
            PrimaryForm.Instance.syncReplayButton.Visible = true;
            PrimaryForm.Instance.syncReplayButton.BringToFront();
            PrimaryForm.Instance.syncOriginalSongButton.Visible = true;
            PrimaryForm.Instance.syncOriginalSongButton.BringToFront();
            PrimaryForm.Instance.syncMuteButton.Visible = true;
            PrimaryForm.Instance.syncMuteButton.BringToFront();
            if (isPaused)
            {
                PrimaryForm.Instance.syncPlayButton.Visible = true;
                PrimaryForm.Instance.syncPlayButton.BringToFront();
            }
            else
            {
                PrimaryForm.Instance.syncPauseButton.Visible = true;
                PrimaryForm.Instance.syncPauseButton.BringToFront();
            }
            PrimaryForm.Instance.syncVolumeUpButton.Visible = true;
            PrimaryForm.Instance.syncVolumeUpButton.BringToFront();
            PrimaryForm.Instance.syncVolumeDownButton.Visible = true;
            PrimaryForm.Instance.syncVolumeDownButton.BringToFront();
            PrimaryForm.Instance.syncMicUpButton.Visible = true;
            PrimaryForm.Instance.syncMicUpButton.BringToFront();
            PrimaryForm.Instance.syncMicDownButton.Visible = true;
            PrimaryForm.Instance.syncMicDownButton.BringToFront();
            PrimaryForm.Instance.syncCloseButton.Visible = true;
            PrimaryForm.Instance.syncCloseButton.BringToFront();

        }
        public void ClosePrimaryScreenPanel()
        {
            try
            {
                PrimaryForm.Instance.primaryScreenPanel.Visible = false;
                PrimaryForm.Instance.syncServiceBellButton.Visible = false;
                PrimaryForm.Instance.syncCutSongButton.Visible = false;
                PrimaryForm.Instance.syncReplayButton.Visible = false;
                PrimaryForm.Instance.syncOriginalSongButton.Visible = false;
                PrimaryForm.Instance.syncMuteButton.Visible = false;
                PrimaryForm.Instance.syncPauseButton.Visible = false;
                PrimaryForm.Instance.syncPlayButton.Visible = false;
                PrimaryForm.Instance.syncVolumeUpButton.Visible = false;
                PrimaryForm.Instance.syncVolumeDownButton.Visible = false;
                PrimaryForm.Instance.syncMicUpButton.Visible = false;
                PrimaryForm.Instance.syncMicDownButton.Visible = false;
                PrimaryForm.Instance.syncCloseButton.Visible = false;
                IsSyncToPrimaryMonitor = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine(String.Format("Error closing primary screen panel: {0}", ex.Message));
                MessageBox.Show(String.Format("Error closing primary screen panel: {0}", ex.Message));
            }
        }

        [DllImport("gdi32.dll", ExactSpelling = true)]
        public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
        IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);

        public enum TernaryRasterOperations : uint
        {
            SRCCOPY = 0x00CC0020,
        }


        private void DisplayBarrageOnOverlay(string text)
        {
            if (overlayForm.InvokeRequired)
                overlayForm.Invoke(new System.Action(() => overlayForm.DisplayBarrage(text)));
            else
                overlayForm.DisplayBarrage(text);
        }

        public async Task PlayNextSong()
        {
            // 等待初始化完成（例如播放器、串口等資源尚未就緒時）
            Console.WriteLine("開始播放下一首歌曲...");
            var songToPlay = SongList.Next();
            if (!songToPlay.isPublicSong)
            {
                // 若是使用者點播模式，先送出升Key的串口指令
                if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen)
                {
                    byte[] commandBytesIncreasePitch1 = new byte[] { 0xA2, 0x7F, 0xA4 };
                    SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch1, 0, commandBytesIncreasePitch1.Length);
                }
            }

            // pathToPlay 需要調整 
            var pathToPlay = songToPlay.getFile();

            // 更新畫面上顯示的下一首歌資訊
            SongList.UpdateNextSongLabel();

            // 顯示 QRCode（可能是點歌頁用）
            overlayForm.DisplayQRCodeOnOverlay(HttpServer.randomFolderPath);

            // 隱藏「暫停中」標籤
            overlayForm.HidePauseLabel();

            await _InitializeAndPlayMedia(pathToPlay);
            
            
        }
        public async Task ReplayCurrentSong()
        {
            var songToPlay = SongList.Current();
            var pathToPlay = songToPlay.getFile();
            // UpdateMarqueeTextForCurrentSong(songToPlay);
            await _InitializeAndPlayMedia(pathToPlay);
        }
        private async Task _InitializeAndPlayMedia(string pathToPlay)
        {
            try
            {
                if (InvokeRequired)
                {
                    await InvokeAsync(() => InitializeAndPlayMedia(pathToPlay));
                }
                else
                {
                    await InitializeAndPlayMedia(pathToPlay);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"播放時發生錯誤: {ex.Message}");
                await RetryInitializeAndPlayMedia(pathToPlay);
            }
        }

        private async Task RetryInitializeAndPlayMedia(string path)
        {
            try
            {
                int hr = CoInitializeEx(IntPtr.Zero, COINIT.APARTMENTTHREADED);
                if (hr >= 0)
                {
                    await InitializeAndPlayMedia(path);
                }
                else
                {
                    Console.WriteLine("CoInitializeEx 失敗，無法重新初始化 COM。");
                }
            }
            catch (Exception retryEx)
            {
                Console.WriteLine($"重試播放時發生錯誤: {retryEx.Message}");
            }
        }

        // 通用的 async invoke 方法（避免重複寫）
        private Task InvokeAsync(Func<Task> func)
        {
            var tcs = new TaskCompletionSource<bool>();
            BeginInvoke(async () =>
            {
                try
                {
                    await func();
                    tcs.SetResult(true);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            });
            return tcs.Task;
        }

        private Task InitializeAndPlayMedia(string pathToPlay)
        {
            // 渲染媒體文件
            primary.RenderMediaFile(pathToPlay,PrimaryForm.Instance.primaryScreenPanel.Handle,newWidth,newHeight);
            secondary.RenderMediaFile(pathToPlay,this.Handle,secondMonitor.Bounds.Width,secondMonitor.Bounds.Height);

            // 音量處理
            SetVolume(isMuted ? -10000 : previousVolume);
            
            // 開始播放
            primary.Run();
            secondary.Run();
            if (isSyncToPrimaryMonitor) SyncToPrimaryMonitor();
            return Task.CompletedTask;
        }

        private void InitializeOverlayForm(Screen secondaryScreen)
        {
            overlayForm = new OverlayForm();
            Screen secondMonitor = ScreenHelper.GetSecondMonitor();
            if (secondMonitor != null)
            {
                overlayForm.Location = secondMonitor.WorkingArea.Location;
                overlayForm.StartPosition = FormStartPosition.Manual;
                overlayForm.Size = new Size(secondMonitor.WorkingArea.Width, secondMonitor.WorkingArea.Height);
            }
            overlayForm.ShowInTaskbar = false;
            overlayForm.Owner = this;
            overlayForm.Show();
            this.Focus();
        }

        public void MonitorMediaEvents()
        {
            Task.Run(async () =>
            {
                Console.WriteLine("開始監聽媒體事件...");
                while (true)
                {
                    try
                    {
                        bool isAtEnd = secondary.isAtEnd() ;
                        if (isAtEnd && !isPaused)
                        {
                            BeginInvoke(new Action(async () =>
                            {
                                await PlayNextSong();
                            }));
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"監控媒體事件時發生錯誤: {ex.Message}");
                        await Task.Delay(1000);
                    }

                    await Task.Delay(1000);
                }
            });
        }

        public void BringOverlayToFront()
        {
            if (overlayForm != null)
            {
                if (!overlayForm.Visible)
                {
                    overlayForm.Show();
                }

                overlayForm.BringToFront();
                overlayForm.TopMost = true;
            }
        }

        public void Play()
        {
            primary.Run();
            secondary.Run();
            isPaused = false;
            OverlayForm.MainForm.HidePauseLabel();
        }

        public void Stop()
        {
            primary.Stop();
            secondary.Stop();
        }

        public void Pause()
        {
            primary.Pause();
            secondary.Pause();
            isPaused = true;
            OverlayForm.MainForm.ShowPauseLabel();
        }
        public void PauseOrResumeSong()
        {
            if (isPaused)
            {
                Play();
                PrimaryForm.Instance.pauseButton.Visible = true;
                PrimaryForm.Instance.playButton.Visible = false;
                PrimaryForm.Instance.syncPauseButton.Visible = true;
                PrimaryForm.Instance.syncPlayButton.Visible = false;
            }
            else
            {
                Pause();
                PrimaryForm.Instance.pauseButton.Visible = false;
                PrimaryForm.Instance.playButton.Visible = true;
                PrimaryForm.Instance.syncPauseButton.Visible = false;
                PrimaryForm.Instance.syncPlayButton.Visible = true;
                OverlayForm.MainForm.ShowPauseLabel();
            }
        }
        private void UpdateSyncButtons()
        {
            if (isPaused)
            {
                PrimaryForm.Instance.syncPlayButton.Visible = true;
                PrimaryForm.Instance.syncPauseButton.Visible = false;
            }
            else
            {
                PrimaryForm.Instance.syncPlayButton.Visible = false;
                PrimaryForm.Instance.syncPauseButton.Visible = true;
            }
        }
        public void SetVolume(int volume)
        {
            secondary.SetVolume(volume);
        }
        public int GetVolume()
        {
            return secondary.GetVolume();
        }
        
        public void ToggleVocalRemoval()
        {
            OverlayForm.MainForm.ShowTopRightLabelTime(secondary.ToggleVocalRemoval() ? "無人聲" : "有人聲");
        }
    }
}


