using LibVLCSharp.Shared;

namespace DualScreenDemo.Services
{
    public class MediaService : IDisposable
    {
        private readonly LibVLC _libVLC;
        private readonly MediaPlayer _mediaPlayer;
        private Media? _media;
        private bool _disposed;

        public MediaService(nint handle)
        {
            Core.Initialize();
            _libVLC = new LibVLC(
                "--aout=directsound",
                "--network-caching=300",
                "--file-caching=300",
                "--audio-time-stretch",
                "--video-filter=clone"
                //$"--clone-views={handle}" // 這是 clone 的目標視窗
            );

            _mediaPlayer = new MediaPlayer(_libVLC);
        }

        #region Player Setup
        public void SetVideoOutput(nint handle, int width, int height)
        {
            _mediaPlayer.Hwnd = handle;
            _mediaPlayer.AspectRatio = $"{width}:{height}";
            _mediaPlayer.Scale = 0;
        }
        #endregion

        #region Playback
        public MediaPlayer Player => _mediaPlayer;
        public bool IsPlaying => _mediaPlayer.IsPlaying;

        public bool IsAtEnd()
        {
            var duration = _mediaPlayer.Media?.Duration ?? 0;
            var time = _mediaPlayer.Time;
            return duration > 0 && Math.Abs(duration - time) < 1000;
        }

        public void LoadMedia(string filePath, int audioTrackIndex = 0)
        {
            _mediaPlayer.Stop();
            _media?.Dispose();

            _media = new Media(_libVLC, filePath, FromType.FromPath);
            _media.AddOption(":audio-output=directsound");
            _media.AddOption($":audio-track={audioTrackIndex}");
        }

        public void Play()
        {
            if (_media == null) return;
            _mediaPlayer.Play(_media);
        }
        public void Pause() => _mediaPlayer.Pause();
        public void Stop() => _mediaPlayer.Stop();
        #endregion

        #region Audio
        public List<TrackDescription> GetAudioTracks()
        {
            var result = new List<TrackDescription>();
            var media = _mediaPlayer.Media;

            if (media == null) return result;

            if (!media.IsParsed)
                media.Parse(MediaParseOptions.ParseLocal);

            var tracks = media.Tracks;
            if (tracks == null) return result;

            foreach (var track in tracks.Where(t => t.TrackType == TrackType.Audio))
            {
                result.Add(new TrackDescription
                {
                    Id = track.Id,
                    Name = !string.IsNullOrEmpty(track.Language) ? track.Language : $"Audio Track {track.Id}"
                });
            }
            return result;
        }

        public void SetAudioTrack(int trackIndex)
        {
            var audioTracks = GetAudioTracks();
            if (trackIndex < 0 || trackIndex >= audioTracks.Count) return;
            _mediaPlayer.SetAudioTrack(audioTracks[trackIndex].Id);
        }
        #endregion

        #region Volume
        public void SetVolume(int volume) => _mediaPlayer.Volume = volume;
        public int GetVolume() => _mediaPlayer.Volume;
        public bool Mute(bool isMuted) => _mediaPlayer.Mute = isMuted;
        #endregion

        #region Dispose
        public void Dispose()
        {
            if (_disposed) return;

            _mediaPlayer.Dispose();
            _media?.Dispose();
            _libVLC.Dispose();

            _media = null;
            _disposed = true;
        }
        #endregion
    }

    public class TrackDescription
    {
        public int Id { get; set; }
        public string Name { get; set; } = string.Empty;
    }
}