
#ifndef _ZWROOM_H_
#define _ZWROOM_H_

#include "MFSPublic.h"
#include "MediaClientConnection.h"
#include "Rtp808Protocol.h"
#include "MediaF3Protocol.h"

namespace mfs
{
    enum ZWROOM_STATE
    {
        DEFAULT,                // 初始化状态，等待客户端进入
        CLIENT_CONNECTED,       // 客户端已连接，下发播放指令
        TERMINAL_CONNECTED,     // 终端已连接，等待数据转发
        FORWARDING,             // 数据转发中
        PAUSE,                  // 暂停转发中
        CLOSING,                // 关闭连接中：终端断开&客户端全断开（回放对讲则立马关闭、实时视频则超时断开）
    };

    struct CommandInfo
    {
        std::chrono::time_point<std::chrono::system_clock> LastCmdTime;    // 指令下发时间
        int LastCmdNumber;                                                 // 指令流水号
        std::string CmdID;                                                 // 指令ID
        std::string CmdSubID;                                              // 指令控制参数
    };
    struct PipeInfo
    {
        int length = 0;
        int pipefd[2];
    };

    class ZWRoom: public IMediaF3ProtocolAnswer, public std::enable_shared_from_this<ZWRoom>
    {
    private:
        static std::vector<std::shared_ptr<ZWRoom>> _rooms;                 // 当前所有房间
        static bool _isPlayback;
        static bool _isTalkback;

        std::vector<std::shared_ptr<MediaClientConnection>> _clients;      // 所有的观众
        std::shared_ptr<Rtp808Protocol> _terminal;                            // 音视频源
        
        std::string _uuidKey;                                               // 房间唯一KEY
        std::string _url;                                                   // 房间URL

        std::map<int, CommandInfo> _commandInfos;                           // 下发的指令
        // std::chrono::time_point<std::chrono::system_clock> _lastCmdTime;    // 指令下发时间
        // int _lastCmdNumber;                                                 // 指令流水号

        PlayerSetting _playerSetting;                                       // 播放参数
        MessageBaseSetting _baseSettingF3;                                  // 指令基本参数
        
        // std::map<int, std::string> _msg1078;                             // 下发的1078指令<流水号、消息内容>
        ZWROOM_STATE _state;                                                // 当前房间状态

        int _pipeSize = 0;
        int _pipefd[2] = {-1};                                                      // 0拷贝管道
        std::vector<PipeInfo> _vecPipeArr;                                     // 0拷贝管道
        
        ZWRoom(const std::string& url, const PlayerSetting& setting);
        ZWRoom(ZWRoom&)=delete;
        ZWRoom& operator=(const ZWRoom&)=delete;

        bool checkCommandExists(const std::string& cmdID, const std::string& subCmdID);
        // 播放状态检查
        void checkPlaying();
        // 检查是否时空房间
        void checkEmpty();
        // 指令超时
        void checkCommand();
        // void checkTimeout();


        void alogd(const std::string& message, const std::string& fileName, const int line, const std::string& functionName) 
        {
            LOG_DEBUG2 <<"["<< _url <<"] " <<"["<<mfs::logErrConsole.filtersFileName(fileName)<<":"<<line<<"] "<<functionName<<"(): >>>> " << message <<LOG_ENDL;
        }
        void aloge(const std::string& message, const std::string& fileName, const int line, const std::string& functionName) 
        {
            LOG_ERROR2 <<"["<< _url <<"] " <<"["<<mfs::logErrConsole.filtersFileName(fileName)<<":"<<line<<"] "<<functionName<<"(): >>>> " << message <<LOG_ENDL;
        }
        void alogv(const std::string& message, const std::string& fileName, const int line, const std::string& functionName) 
        {
            LOG_VERBOSE2 <<"["<< _url <<"] " <<"["<<mfs::logErrConsole.filtersFileName(fileName)<<":"<<line<<"] "<<functionName<<"(): >>>> " << message <<LOG_ENDL;
        }
    public:
        ~ZWRoom();

        bool hasClient(){return _clients.size()>0;}
        bool hasTerminal(){return _terminal!=nullptr;}

        /**
         * 
         */ 
        // 设置终端
        void setTerminal(std::shared_ptr<Rtp808Protocol> rtp);
        // 终端数据
        void onRecvDataTerminalEpoll(int fd);
        // 终端数据
        int onDataTerminal(char* data, int dataLength);
        // 终端退出
        void onExitTerminal(std::shared_ptr<Rtp808Protocol> rtp);
        // 终端数据异常
        void onDataError(const std::string&);

        /**
         * 
         */
        // 
        bool appendClient(std::shared_ptr<MediaClientConnection> client);
        // 客户端数据
        void onRecvDataClientEpoll(int fd);
        // 客户端数据
        void onRecvDataClient(BaseProtocol* prot);
        // 客户端二进制数据
        void onDataMediaClient(MediaClientConnection* client, BaseProtocol* proto,char* data, int dataLength);
        // 客户端消息
        void onMessageClient(MediaClientConnection* client, BaseProtocol* proto,cJSON* root);
        // 客户端音频数据数据
        void onAudioDataMediaClient(MediaClientConnection* client, BaseProtocol* proto,char* data, int dataLength);
        // 客户端控制信息
        void onControlMediaClient(MediaClientConnection* client, BaseProtocol* proto,const ControlSetting& setting);
        // 客户端退出
        void onExitClient(MediaClientConnection* client, BaseProtocol* proto);
        // 
        void writeMessageClients(int code, const char* message, int messageLength);
        void writeDataClients(char* data, int dataLength);


        // 1078应答
        void onAnswer1078(int num, int result);
        int play1078();
        bool control1078(const ControlSetting& setting);

        static void checkRooms();
        static void setPlayback(bool v){_isPlayback=v;}
        static void setIsTalkback(bool v){_isTalkback=v;}
        static std::shared_ptr<ZWRoom> findRoomByUrl(const std::string& url);
        static std::string addTerminal(std::shared_ptr<Rtp808Protocol> rtp);
        static std::string addClient(std::shared_ptr<MediaClientConnection> rtp);
    };
    
}
#endif // _ZWROOM_H_