using System;

using System.Threading;

using System.Threading.Tasks;

using Microsoft.Maui.Graphics;


namespace StuckPixelRestore.Services

{

    /// <summary>

    /// 컬러 노이즈를 생성하여 이벤트를 통해 색상을 전달하는 서비스

    /// 주어진 FPS로 랜덤 색상을 생성하며, 지정된 시간 후 자동으로 중단될 수 있음.

    /// </summary>

    public class NoiseService : INoiseService

    {

        private CancellationTokenSource cancellationTokenSource;

        private Action? onStoppedCallback;

        private Random random;

        private double targetFps = 60.0;

        private TimeSpan? autoStopDuration;

        private DateTime startTime;

        private bool isRunning;


        /// <summary>

        /// 노이즈 생성 실행 상태 변경 이벤트.

        /// </summary>

        public event EventHandler<bool> IsRunningChanged;


        /// <summary>

        /// 랜덤 색상 생성 이벤트.

        /// </summary>

        public event EventHandler<Color> ColorGenerated;


        /// <summary>

        /// 현재 노이즈 생성이 실행 중인지 여부를 반환.

        /// </summary>

        public bool IsRunning => isRunning;


        /// <summary>

        /// NoiseService 생성자.

        /// </summary>

        public NoiseService()

        {

            random = new Random();

        }


        /// <summary>

        /// 노이즈 생성을 시작.

        /// </summary>

        /// <param name="onStoppedCallback">노이즈 생성이 종료될 때 호출할 선택적 콜백 함수.</param>

        /// <exception cref="InvalidOperationException">이미 실행 중인 경우 발생.</exception>

        public void StartNoise(Action? onStoppedCallback = null)

        {

            if (isRunning)

            {

                throw new InvalidOperationException("[NoiseService] 이미 노이즈가 실행 중입니다.");

            }


            StopNoise(); // 안전하게 이전 세션 정리

            isRunning = true;

            this.onStoppedCallback = onStoppedCallback;

            cancellationTokenSource = new CancellationTokenSource();

            startTime = DateTime.UtcNow;

            IsRunningChanged?.Invoke(this, true);


            Task.Run(async () =>

            {

                double frameDelayMs = 1000.0 / targetFps;


                while (!cancellationTokenSource.Token.IsCancellationRequested)

                {

                    try

                    {

                        // 랜덤 컬러 생성

                        Color randomColor = Color.FromRgb(

                            random.NextDouble(),

                            random.NextDouble(),

                            random.NextDouble()

                        );


                        ColorGenerated?.Invoke(this, randomColor);


                        // 자동 종료 시간 체크

                        if (autoStopDuration.HasValue)

                        {

                            TimeSpan elapsed = DateTime.UtcNow - startTime;

                            if (elapsed >= autoStopDuration.Value)

                            {

                                StopNoise();

                                break;

                            }

                        }


                        await Task.Delay(TimeSpan.FromMilliseconds(frameDelayMs), cancellationTokenSource.Token);

                    }

                    catch (TaskCanceledException)

                    {

                        // 정상 종료 상황 - 무시

                        break;

                    }

                    catch (Exception ex)

                    {

                        Console.WriteLine($"[NoiseService] 오류 발생: {ex.Message}");

                        StopNoise();

                        break;

                    }

                }

            });

        }


        /// <summary>

        /// 노이즈 생성을 강제로 중단.

        /// </summary>

        public void StopNoise()

        {

            if (!isRunning)

            {

                return;

            }


            cancellationTokenSource?.Cancel();

            cancellationTokenSource?.Dispose();

            cancellationTokenSource = null;


            isRunning = false;

            IsRunningChanged?.Invoke(this, false);


            onStoppedCallback?.Invoke();

            onStoppedCallback = null;

        }


        /// <summary>

        /// 목표 FPS(Frame Per Second)를 설정.

        /// </summary>

        /// <param name="fps">초당 프레임 수 (60.0 등).</param>

        /// <exception cref="ArgumentOutOfRangeException">FPS가 0 이하인 경우 발생.</exception>

        public void SetTargetFps(double fps)

        {

            if (fps <= 0)

            {

                throw new ArgumentOutOfRangeException(nameof(fps), "[NoiseService] FPS는 0보다 커야 합니다.");

            }

            targetFps = fps;

        }


        /// <summary>

        /// 자동으로 노이즈 생성이 중단될 시간을 설정.

        /// </summary>

        /// <param name="duration">자동 정지까지의 시간. null이면 무제한.</param>

        /// <exception cref="ArgumentOutOfRangeException">duration이 0 이하일 경우 발생.</exception>

        public void SetAutoStopDuration(TimeSpan? duration)

        {

            if (duration.HasValue && duration.Value <= TimeSpan.Zero)

            {

                throw new ArgumentOutOfRangeException(nameof(duration), "[NoiseService] duration은 0보다 커야 합니다.");

            }

            autoStopDuration = duration;

        }

    }

}



걍 앱은 좆까라하고 그냥 구현만 하면되니까 더 쉽네 씨발ㅋㅋ