using System;
using System.Collections.Generic;

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Channels;
using ProtoDataBuff;

using CSharpUtil;

namespace MultiDup
{


    /// <summary>
    /// 大厅 首先玩家连上来之后进入大厅, 下发当前房间列表, 可以创建/加入房间, 进入房间后归房间管
    /// </summary>
    internal class Lobby : Singleton<Lobby>
    {

        /// <summary>
        /// 客户端
        /// </summary>
        public Dictionary<int, Peer> ClientPeers = new Dictionary<int, Peer>();
        /// <summary>
        /// 消息分发
        /// </summary>
        private Dictionary<eProtocalCommand, Action<int, sSocketData>> callbacks = new Dictionary<eProtocalCommand, Action<int, sSocketData>>();

        /// <summary>
        /// 客户端消息队列
        /// </summary>
        public Channel<KeyValuePair<int, sSocketData>> MsgChannel = Channel.CreateBounded<KeyValuePair<int, sSocketData>>(1000);


        Dictionary<int, Room> roomDic = new Dictionary<int, Room>();


        public Lobby()
        {
            this.callbacks.Add(eProtocalCommand.CsMdEnterLobby, On_EnterLobby);
            this.callbacks.Add(eProtocalCommand.CsLeaveRoom, On_Leave);
            callbacks.Add(eProtocalCommand.CsMdGetRoomList, On_GetRoomList);
            callbacks.Add(eProtocalCommand.CsMdCreateRoom, On_CreateRoom);
            callbacks.Add(eProtocalCommand.CsMdEnterRoom, On_EnterRoom);
            var t = Task.Run(MsgLoop);

        }
        private object lock_peers = new object();
        public void AddPeer(Peer p)
        {
            lock (lock_peers)
            {
                this.ClientPeers.Add(p.Id, p);
            }

        }
        public void RemovePeer(int peerId)
        {
            lock (lock_peers)
            {
                if (this.ClientPeers.ContainsKey(peerId))
                {
                    this.ClientPeers.Remove(peerId);
                }
            }
        }


        public void RemoveRoom(int roomid) { 
            roomDic.Remove(roomid);
        }

        public void OnNewPeerConnected(Peer peer)
        {
            AddPeer(peer);
        }

        /// <summary>
        /// 进入大厅(登陆自己的uid)
        /// </summary>
        /// <param name="data"></param>
        void On_EnterLobby(int peerId, sSocketData data)
        {
            var msg = CS_MD_EnterLobby.Parser.ParseFrom(data._data);

            if (this.ClientPeers.TryGetValue(peerId, out var peer))
            {
                peer.SendEvent(eProtocalCommand.ScMdEnterLobby, new SC_MD_EnterLobby() { });
                peer.CurrentState = ClientState.InLobby;
                peer.Properties.Add(PropertyName.Uid, msg.Uid);
                peer.Properties.Add(PropertyName.Zoneid, msg.Zoneid);
            }
        }

        /// <summary>
        /// 查询房间列表
        /// </summary>
        /// <param name="data"></param>
        void On_GetRoomList(int peerId, sSocketData data)
        {

            var msg = new SC_MD_GetRoomList() { };
            if (this.ClientPeers.TryGetValue(peerId, out var peer))
            {
                this.roomDic.Values.ToList().ForEach(r =>
                {
                    var info = new SC_MD_GetRoomList.Types.RoomInfo() { Battleserver =r.BattleServerIp, BattleServerPort=r.BattleServerPort, Mapid = r.mapId, RoomId = r.Id };
                    r.ClientPeers.Values.ToList().ForEach(peer =>
                    {
                        info.PlayerUids.Add(peer.UID);
                    });
                    msg.RoomInfos.Add(info);
                });

                peer.SendEvent(eProtocalCommand.ScMdGetRoomList, msg);
            }
        }
        /// <summary>
        /// 创建一个房间(副本)
        /// </summary>
        /// <param name="data"></param>
        void On_CreateRoom(int peerId, sSocketData data)
        {
            var msg = CS_MD_CreateRoom.Parser.ParseFrom(data._data);
            if (this.ClientPeers.TryGetValue(peerId, out var peer))
            {
                peer.SendEvent(eProtocalCommand.ScMdCreateRoom, new SC_MD_CreateRoom() { });
                var room = new Room(msg.Mapid);
                room.AddPeer(peer);                   // 转移进房间
                roomDic.Add(room.Id, room);
                 
                //RemovePeer(peerId);                                                  // 从大厅移除
            }
        }

        /// <summary>
        /// 进入房间
        /// </summary>
        /// <param name="data"></param>
        void On_EnterRoom(int peerId, sSocketData data)
        {
            var msg = CS_MD_EnterRoom.Parser.ParseFrom(data._data);
            if (this.ClientPeers.TryGetValue(peerId, out var peer))
            {
                if (roomDic.TryGetValue(msg.RoomId, out var room))
                {
                    room.AddPeer(peer);
                }

            }
        }

        /// <summary>
        /// 离开房间(战斗结束)
        /// </summary>
        /// <param name="data"></param>
        void On_Leave(int peerId, sSocketData data)
        {
            if (this.ClientPeers.TryGetValue(peerId, out var peer))
            {
                peer.SendEvent(eProtocalCommand.ScMdLeaveRoom, new SC_MD_LeaveRoom() { });
                peer.Close();
            }
        }

        async void MsgLoop()
        {
            while (true)
            {
                var msg = await MsgChannel.Reader.ReadAsync();
                if (callbacks.ContainsKey(msg.Value._protocallType))
                {
                    callbacks[msg.Value._protocallType](msg.Key, msg.Value);
                }
                else
                {
                    // 未找到消息处理逻辑
                }
            }
        }
    }
}
