using fis.media.Library.Media.Members;
using fis.media.Library.Media.Players;
using fis.media.Library.Media.Publisher;
using fis.media.Library.Media.Rooms;
using fis.media.Library.OutPut.FisVideoFrameOutput;
using fis.media.Library.Players;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace fis.media.Managers
{
    public class ChatRoomManager
    {        
        private ChatRoomManager()
        {
            Pusher =PusherManager.Instance;
            Player = PlayerManager.Instance;
            //默认为TRTC房间
            RoomType = RoomTypeEnum.TRTCRoom;
            _videoStreamStructre = new VideoStreamStructre();
        }
        private static ChatRoomManager _instance;
        private RoomTypeEnum _roomType;
        private VideoStreamStructre _videoStreamStructre;

        public static ChatRoomManager Instance => _instance ?? (_instance = new ChatRoomManager());
        public IRoom Room { get; private set; }
        public PusherManager Pusher { get; set; }
        public PlayerManager Player { get; set; }
        
        public event EventHandler<VideoStreamStructre> VideoStreamOutputInvoked;
        
      
        /// <summary>
        /// 进入房间
        /// </summary>
        /// <param name="roomType"></param>
        /// <param name="members"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public bool Enter(RoomTypeEnum roomType, List<AbstractMember> members,string[] args)
        {
            RoomType = roomType;
            foreach (var c in members)
            {
                Room.EnterRoom(c);
            }
            var memebers = Room.Members;
            foreach (var m in memebers)
            {
                var channels = m.Player.PlayerChannels;
                foreach (var channel in channels)
                {
                    channel.FrameRecieved += OnChannelFrameRevieved;
                }
            }
            var commonStartupArgs= new List<string> { $"{RoomType}" }; 
         
            foreach (var arg in args)
            {
                commonStartupArgs.Add(arg);
            }
            Pusher.Start(commonStartupArgs.ToArray());

            Pusher.PreviewImageReceived += OnPreviewImageReceived;

            Player.Start(commonStartupArgs.ToArray());

            return true;
        }

        private void OnPreviewImageReceived(object? sender, LocalPreviewVideoFrameData e)
        {
            var selfMember = Room.Members.FirstOrDefault(x => x.Id == e.UserId);
           var activeMember= selfMember as ActiveMember;
            var channelVideoFrame = new ChannelVideoFrame(e.Data,activeMember.Id, ChannelNameEnum.Main,activeMember.RoleType);
            OnChannelFrameRevieved(this, channelVideoFrame);
        }

        private void OnChannelFrameRevieved(object? sender, ChannelVideoFrame e)
        {
            var existOuput = _videoStreamStructre.VideoChannels.FirstOrDefault(x => x.Id == e.ChannelOwnerId
                && x.ChannelDisplayName == e.ChannelNameEnum.ToString());
            if (existOuput == null)
            {
                var outPut = GenerateOutput(e);
                outPut.UpdataFrameData(e.VideoFrameData.ToBase64());
                _videoStreamStructre.VideoChannels.Add(outPut);
            }
            else
            {
                existOuput.UpdataFrameData(e.VideoFrameData.ToBase64());
            }
            VideoStreamOutputInvoked?.Invoke(this,_videoStreamStructre);
        }

     
        /// <summary>
        /// 更新成员状态
        /// </summary>
        /// <param name="abstractMember"></param>
        /// <returns></returns>
        public bool UpdateMember(AbstractMember abstractMember)
        {
            var memeber = Room.Members.FirstOrDefault(x => x.Id == abstractMember.Id);
            if (memeber == null)
            {
                return false;
            }
            var activeExistMemeber= memeber as ActiveMember;
            var activeMemeber = abstractMember as ActiveMember;
            if (activeMemeber != null && activeExistMemeber != null)
            {
                activeExistMemeber.IsOnline = activeMemeber.IsOnline;
                activeExistMemeber.IsMute = activeMemeber.IsMute;
                activeExistMemeber.IsCameraOn = activeExistMemeber.IsCameraOn;
                activeExistMemeber.IsMergeChannel = activeExistMemeber.IsMergeChannel;
                return activeExistMemeber.AdaptMemberUpdate();
            }
            return true;
          
        }

        /// <summary>
        /// 删除成员
        /// </summary>
        /// <param name="abstractMember"></param>
        /// <returns></returns>
        public bool RemoveMember(AbstractMember abstractMember)
        {
            var memeber = Room.Members.FirstOrDefault(x => x.Id == abstractMember.Id);
            if (memeber == null)
            {
                return false;
            }
            memeber.Dispose();
            Room.Members.Remove(memeber);
            return true;

        }

        public bool Exit()
        {
            Pusher.Dispose();
            Player.Dispose();
          
            var memebers = Room.Members;
           
            foreach (var m in memebers)
            {
                var channels = m.Player.PlayerChannels;
                foreach (var channel in channels)
                {
                    channel.FrameRecieved -= OnChannelFrameRevieved;
                }
            }

            Room.Dispose();
            return true;
        }

        private RoomTypeEnum RoomType
        {
            get
            {
                return _roomType;
            }
            set
            {
                if (_roomType != value)
                {
                    _roomType = value;
                    SwithRoom();
                }
            }
        }


        private void SwithRoom()
        {
            Room?.Dispose();
            Room = null;
            if (RoomType == RoomTypeEnum.TRTCRoom)
            {
                Room = TRTCRoom.Instance;
            }
            if (RoomType == RoomTypeEnum.RTMPVirtualRoom)
            {
                Room = RTMPRoom.Instance;
            }
            if (RoomType == RoomTypeEnum.VRTCRoom)
            {
                Room = VRTCRoom.Instance;
            }
        }

        private Channelbase GenerateOutput(ChannelVideoFrame e)
        {
            if (e.OwnerRoleType == MemeberTypeEnum.LocalVideo)
            {
                return new LocalCameraChannel(e.ChannelOwnerId, e.ChannelNameEnum.ToString());

            }
            if (e.OwnerRoleType == MemeberTypeEnum.RemoteVideo)
            {
                return new RemoteCameraChannel(e.ChannelOwnerId, e.ChannelNameEnum.ToString());
            }
            if (e.OwnerRoleType == MemeberTypeEnum.MainDeviceVideo)
            {
                if (e.ChannelNameEnum == ChannelNameEnum.Main)
                {
                    return new MainChannel(e.ChannelOwnerId, e.ChannelNameEnum.ToString());
                }
                if (e.ChannelNameEnum == ChannelNameEnum.SideOne)
                {
                    return new SideChannelOne(e.ChannelOwnerId, e.ChannelNameEnum.ToString());
                }
                if (e.ChannelNameEnum == ChannelNameEnum.SideTwo)
                {
                    return new SideChannelTwo(e.ChannelOwnerId, e.ChannelNameEnum.ToString());
                }
            }
            return null;
        }


    }
}