using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;
using FFmpeg.AutoGen;
using SmartAquaViewer.Helper.FFHelper;
using SmartAquaViewer.Model;

namespace SmartAquaViewer.ViewModel
{
    public class FFPlayerViewModel : INotifyPropertyChanged
    {
        public CCTVInfo CCTVInfo { get; set; }

        private ImageSource? _currentFrame;
        public ImageSource? CurrentFrame
        {
            get => _currentFrame;
            set { _currentFrame = value; OnPropertyChanged(); }
        }

        private readonly object _lockObject = new object();
        private Thread _videoThread;
        private Thread _renderingThread;
        private CancellationTokenSource _videoCancellationTokenSource;
        private CancellationTokenSource _renderingCancellationTokenSource;
        private bool _stopThread = false;

        private ConcurrentQueue<Bitmap> _frameQueue = new ConcurrentQueue<Bitmap>();

        public FFPlayerViewModel(CCTVInfo cctvInfo)
        {
            CCTVInfo = cctvInfo;
        }

        public void StartMedia(string rtspURL)
        {
            ClosePlayer();
            _stopThread = false;

            _videoThread = new Thread(new ThreadStart(OpenMedia));
            _renderingThread = new Thread(new ThreadStart(RenderImage));

            _videoThread.Priority = ThreadPriority.Highest; // 우선순위 설정
            _videoThread.Start();

            _renderingThread.Start();
        }

        private unsafe void OpenMedia()
        {
            int failCount = 0;
            int frameCount = 0;

            _frameQueue = new ConcurrentQueue<Bitmap>();
            _videoCancellationTokenSource = new CancellationTokenSource();

            try
            {
                using (StreamDecoder sd = new StreamDecoder(CCTVInfo.RtspUrl))
                {
                    using (var vfc = new VideoFrameConverter(sd.FrameSize, sd.PixelFormat, sd.FrameSize, AVPixelFormat.AV_PIX_FMT_BGR24))
                    {
                        while (!_videoCancellationTokenSource.Token.IsCancellationRequested)
                        {
                            bool decodeSuccess = sd.TryDecodeNextFrame(out var frame);

                            //if (!decodeSuccess)
                            //{
                            //    failCount++;
                            //    HandleDecodeFailure(ref failCount, maxFailCount);
                            //    continue; // 다음 반복으로 이동
                            //}

                            // 디코딩 성공 시 프레임 처리
                            HandleDecodedFrame(frame, vfc, ref frameCount);
                            failCount = 0; // 실패 카운트 초기화
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //Log4NetManager.GetLog().Error("OpenMedia() : " + ex.Message);
                Debug.WriteLine("OpenMedia() : " + ex.Message.ToString());
            }
            finally
            {
                if (!_stopThread || !_videoCancellationTokenSource.Token.IsCancellationRequested)
                {
                    Debug.WriteLine($"Restarting media");
                    StartMedia(CCTVInfo.RtspUrl);
                }
            }
        }

        private void HandleDecodedFrame(AVFrame frame, VideoFrameConverter vfc, ref int frameCount)
        {
            Bitmap convertedFrame = null;

            try
            {
                convertedFrame = vfc.DeepCopyFrame(frame);

                lock (_lockObject)
                {
                    _frameQueue.Enqueue(convertedFrame);
                    frameCount++;
                }
            }
            catch (Exception ex)
            {
                //Log4NetManager.GetLog().Error("HandleDecodedFrame() : " + ex.Message);
                Debug.WriteLine("HandleDecodedFrame() : " + ex.Message);
                convertedFrame?.Dispose();
            }
        }

        private void RenderImage()
        {
            int dequeCount = 0;

            _renderingCancellationTokenSource = new CancellationTokenSource();

            try
            {
                while (!_renderingCancellationTokenSource.Token.IsCancellationRequested)
                {
                    Bitmap bitmap = null;

                    lock (_lockObject)
                    {
                        if (_frameQueue.Count > 0)
                        {
                            _frameQueue.TryDequeue(out bitmap);
                        }
                        else
                        {
                            continue;
                        }
                    }

                    if (bitmap == null)
                    {
                        Thread.Sleep(10); // CPU 과부하 방지
                        continue;
                    }

                    try
                    {
                        //Dispatcher.BeginInvoke((Action)(() =>
                        //{
                        //    try
                        //    {
                        //        DivideAndDisplayBitmap(bitmap);
                        //    }
                        //    finally
                        //    {
                        //        bitmap.Dispose(); // 자원 해제
                        //    }
                        //}));
                    }
                    catch (ArgumentException ex)
                    {
                        Console.WriteLine("RenderImage() : " + ex.Message);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("RenderImage() : " + ex.ToString());
                    }

                    _renderingCancellationTokenSource.Token.ThrowIfCancellationRequested();
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("RenderImage() : Render loop canceled.");
            }
            finally
            {
                // 필요한 자원 정리
                //ClearFrameQueue();
            }
        }

        public void ClosePlayer()
        {
            _stopThread = true;

            lock (_lockObject)
            {
                if (_videoCancellationTokenSource != null)
                {
                    _videoCancellationTokenSource.Cancel();
                    Debug.WriteLine("ClosePlayer(): videoThread 종료함");
                }

                if (_renderingCancellationTokenSource != null)
                {
                    _renderingCancellationTokenSource.Cancel();
                    Debug.WriteLine("ClosePlayer(): RenderingThread 종료함");
                }
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string? name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
