

#include "BaseProtocol.h"
#include "ZWRoom.h"
#include "AppSetting.h"
#include "ZWForwardEpoll.h"
#include "MediaF3Kafka.h"

namespace mfs
{
    bool ZWRoom::_isPlayback = false;
    bool ZWRoom::_isTalkback = false;

    static void GenerateUUID(std::string& str)
    {
        uuid_t uu;
        uuid_generate(uu);

        char buf[64];
        for(auto i=0; i<16; i++)
            sprintf(buf+i*2, "%02X", uu[i]);
        
        str = buf;
    }

    std::vector<std::shared_ptr<ZWRoom>> ZWRoom::_rooms;                                  // 当前所有房间

    ZWRoom::ZWRoom(const std::string& url, const PlayerSetting& setting)
    { 
        _url = url;
        GenerateUUID(_uuidKey);
        logd("create room : uuid="+_uuidKey);
        _playerSetting = setting;
        if (_playerSetting.forward0Copy == "1")
        {
            auto iret = pipe(_pipefd);
            if (iret < 0)
            {
                loge("Failed to create pipe");
            }
        }
    }
    
    ZWRoom::~ZWRoom()
    {
        if (_pipefd[0]>-1)
        {
            close(_pipefd[0]);
            close(_pipefd[1]);

        }
        for (auto iter = _vecPipeArr.begin(); iter != _vecPipeArr.end(); iter++)
        {
            close(iter->pipefd[0]);
            close(iter->pipefd[1]);
        }
        _vecPipeArr.clear();
        
        logd("close room."+_uuidKey);
    }

    void ZWRoom::checkRooms()
    {
        for (auto begin = _rooms.begin(); begin != _rooms.end(); begin++)
        {
            auto  proom = *begin;
            proom->checkPlaying();
            proom->checkEmpty();
            proom->checkCommand();
        }
    }
    std::shared_ptr<ZWRoom> ZWRoom::findRoomByUrl(const std::string& url)
    {
        for (auto begin = _rooms.begin(); begin != _rooms.end(); begin++)
        {
            auto  proom = *begin;
            // LOG_VERBOSE <<"room url="<<proom->_url<<"; url="<<url<<LOG_ENDL;
            if (IsContainsStr(url,proom->_url))
            {
                return proom;
            }
        }
        return nullptr;
    }
    std::string ZWRoom::addTerminal(std::shared_ptr<Rtp808Protocol> rtp)
    {
        auto room = findRoomByUrl(rtp->getUrl());
        if (!room)
        {
            // room = std::shared_ptr<ZWRoom>(new ZWRoom());//std::make_shared<ZWRoom>();
            // room->setUrl(rtp->getUrl());
            // _rooms.push_back(room);
            return "";
        }
        room->setTerminal(rtp);
        return room->_uuidKey;
    }
    std::string ZWRoom::addClient(std::shared_ptr<MediaClientConnection> client)
    {
        auto room = findRoomByUrl(client->getUrl());
        if (room)
        {
            // 已有客户端,重新下发播放
            for (auto iter = room->_clients.begin(); iter != room->_clients.end(); iter++)
            {
                if (iter->get() == client.get())
                {
                    room->_playerSetting = client->getPlayerSetting();
                    auto bret = room->play1078();
                    if (bret == -1)
                    {
                        LOG_DEBUG<<("PlayCommandFail")<<LOG_ENDL;
                        client->sendMessage(EErrorCode::PlayCommandFail);
                    }
                    else if (bret == -2)
                    {
                        LOG_DEBUG<<("DuplicateCommand")<<LOG_ENDL;
                        client->sendMessage(EErrorCode::DuplicateCommand);
                    }
                    return room->_uuidKey;
                }
            }
            // 
            if ((_isPlayback||_isTalkback))//&&room->_clients.size()>0)
            {
                if (room->_clients.size()>0)
                {
                    client->sendMessage(EErrorCode::ChannelBusy);
                }
                else
                {
                    client->sendMessage(EErrorCode::TerminalBusy);
                }
                return "";
            }
            else
            {
            }
        }
        else
        {
            room = std::shared_ptr<ZWRoom>(new ZWRoom(client->getUrl(), client->getPlayerSetting()));//std::make_shared<ZWRoom>();
            room->_baseSettingF3.simcard = room->_playerSetting.simcardNumber;
            room->_baseSettingF3.deviceID = room->_playerSetting.deviceID;
            room->_baseSettingF3.vehicleId = room->_playerSetting.vehicleId;
            room->_baseSettingF3.channelNum = room->_playerSetting.channelNumber;
            room->_baseSettingF3.answer = room;
            
            bool bret = room->play1078();
            if (bret == -1)
            {
                LOG_DEBUG<<("PlayCommandFail")<<LOG_ENDL;
                client->sendMessage(EErrorCode::PlayCommandFail);
            }
            else if (bret == -2)
            {
                LOG_DEBUG<<("DuplicateCommand")<<LOG_ENDL;
                client->sendMessage(EErrorCode::DuplicateCommand);
            }
            _rooms.push_back(room);
        }
        if(!room->appendClient(client)){
            return "";
        }
        client->setOnAudioDataCallback(std::bind(&ZWRoom::onAudioDataMediaClient, room, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
        client->setOnDataCallback(std::bind(&ZWRoom::onDataMediaClient, room, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
        client->setOnControlMediaClient(std::bind(&ZWRoom::onControlMediaClient, room, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
        client->setOnRelease(std::bind(&ZWRoom::onExitClient, room, std::placeholders::_1, std::placeholders::_2));

        return room->_uuidKey;
    }

    bool ZWRoom::appendClient(std::shared_ptr<MediaClientConnection> client)
    {
        logd("_playerSetting.forward0Copy==" + _playerSetting.forward0Copy);
        if (_playerSetting.forward0Copy == "1")
        {
            PipeInfo pi;
            auto iret = pipe(pi.pipefd);
            if (iret < 0)
            {
                loge("Failed to create pipe");
                return false;
            }
            _vecPipeArr.push_back(pi);
        }
        _clients.push_back(client);
        
        if (_terminal)
        {
            client->sendMessage(EErrorCode::ConnectTerminal);
        }

        if (_playerSetting.forward0Copy == "1")
        {
            logd("client add epoll!");
            client->Handle()->stop();
            ZWForwardEpoll::instance()->add(client->getfd(), std::bind(&ZWRoom::onRecvDataClientEpoll, this, std::placeholders::_1));
        }
        return true;
    }

    void ZWRoom::setTerminal(std::shared_ptr<Rtp808Protocol> rtp)
    {
        
        std::shared_ptr<Rtp808Protocol> oldRtp = _terminal;
        _terminal = rtp;
        _terminal->updateStreamInfo(_playerSetting.vehicleId, "0", _uuidKey);
        if (oldRtp)
        {
            // 停止时先调了CLBS再调的音视频服务器,导致错乱
            loge("Exists terminal!");
            oldRtp->Close();
        }
        rtp->SetOnDataCallback(std::bind(&ZWRoom::onDataTerminal, this, std::placeholders::_1, std::placeholders::_2));
        rtp->SetOnDataErrorCallback(std::bind(&ZWRoom::onDataError, this, std::placeholders::_1));
        rtp->SetOnReleaseCallback(std::bind(&ZWRoom::onExitTerminal, this, std::placeholders::_1));
        // rtp->SetOnBeforeDataCallback(std::bind(&ZWRoom::onRecvDataTerminal, this, std::placeholders::_1, std::placeholders::_2));
        if (_playerSetting.forward0Copy == "1")
        {
            logd("terminal add epoll!");
            rtp->Handle()->stop();
            ZWForwardEpoll::instance()->add(rtp->getfd(), std::bind(&ZWRoom::onRecvDataTerminalEpoll, this, std::placeholders::_1));
        }
        
        

        for(auto client : _clients)
        {
            client->sendMessage(EErrorCode::ConnectTerminal);
        }
    }
    // 客户端数据
    void ZWRoom::onRecvDataClientEpoll(int fd)
    {
        if (fd == UV_EINVAL || fd == UV_EBADF)
        {
            loge("error fd: "+std::string(fd == UV_EINVAL?"UV_EINVAL":"UV_EBADF"));
            return;
        }
        if (!_terminal)
        {
            return;
        }
        _terminal->UpdateConnectionFlag(_clients.size()>0?1:0);
        
        for (auto i = 0; i < _clients.size(); i++)
        {
            auto iterClient = _clients.begin()+i;
            if ((*iterClient)->getfd() == fd)
            {
                (*iterClient)->OnRecvData();
            }
        }
    }
    // 终端数据
    void ZWRoom::onRecvDataTerminalEpoll(int fd)
    {
        // logv("onRecvDataTerminalEpoll");
        _terminal->FlushAllData();
        _terminal->UpdateConnectionFlag(_clients.size()>0?1:0);

        if (fd == UV_EINVAL || fd == UV_EBADF)
        {
            loge("error fd: "+std::string(fd == UV_EINVAL?"UV_EINVAL":"UV_EBADF"));
            return;
        }

        auto bufferSize = 2048;
        char readbuffer[2048];
        while (true)
        {
            // logd("onRecvDataTerminal - read");
            auto isbreak = false;
            if (_pipeSize<=0)
            {
                _pipeSize = 0;
                auto iret = splice(fd, NULL, _pipefd[1], NULL, bufferSize, SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
                // auto iret = read(fd, readbuffer, 1024);
                if (iret<=0)
                {
                    if (errno == EAGAIN || errno == EWOULDBLOCK)
                    {
                    }
                    else
                    {
                        loge("error splice from terminal:"+std::to_string(iret)+",errno="+std::to_string(errno));
                        _terminal->Close();
                    }
                    isbreak = true;
                }
                else
                {
                    // write(_pipefd[1], readbuffer, iret);
                    _pipeSize += iret;
                }
            }
            else
            {
                if (!_isPlayback)
                {
                    // loge("Read buffer full!");
                    // _streamInfo.message = "Buffer full(r)!";
                    // this->Close();
                }
                isbreak = true;
            }
            
            // logv("onRecvDataTerminalEpoll - save:"+std::to_string(_pipeSize));
            // 数据放入缓存
            if (_pipeSize>0)
            {
                int wirtedLength = 0;
                char headBuf[32] = {0};
                for (auto i = 0; i < _clients.size(); i++)
                {
                    auto iterClient = _clients.begin()+i;
                    auto iterPipe = _vecPipeArr.begin()+i;

                    // 缓存有数据, 实时视频跳过，回放则阻塞
                    if (iterPipe->length > 0)
                    {
                        if (_isPlayback)
                        {
                            wirtedLength = 0;
                        }
                        logv("onRecvDataTerminal - save: _isPlayback"+std::to_string(_isPlayback));
                        continue;
                    }
                    
                    // 写协议头部
                    iterPipe->length = 0;
                    int headLen = 32;
                    int iret = 0;
                    (*iterClient)->generatePackageHead(_pipeSize, headBuf, headLen);
                    if (headLen>0)
                    {
                        iret = write(iterPipe->pipefd[1], headBuf, headLen);
                        if (iret != headLen)
                        {
                            loge("客户端缓存头部写入失败：" + iret);
                            continue;
                        }
                        iterPipe->length += headLen;
                    }

                    // 写数据-管道实际上不该写入失败
                    if ( i == _clients.size() - 1)
                    {
                        iret = splice(_pipefd[0], NULL, iterPipe->pipefd[1], NULL, _pipeSize, SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
                    }
                    else
                    {
                        iret = tee(_pipefd[0], iterPipe->pipefd[1], _pipeSize, 0);
                    }
                    if (iret != _pipeSize)
                    {
                        loge("客户端缓存数据写入失败：" + std::to_string(iret)+"/"+std::to_string(_pipeSize));
                    }
                    if (iret > 0)
                    {
                        iterPipe->length += iret;
                        wirtedLength = iret;
                    }

                    // 写协议尾部
                    int tailLen = 32;
                    (*iterClient)->generatePackageTail(_pipeSize, headBuf, tailLen);
                    if (tailLen>0)
                    {
                        iret = write(iterPipe->pipefd[1], headBuf, tailLen);
                        if (iret != tailLen)
                        {
                            loge("客户端缓存尾部写入失败：" + iret);
                            continue;
                        }
                        iterPipe->length += tailLen;
                    }
                }
                _pipeSize -= wirtedLength;
                if (wirtedLength<=0 && !_isPlayback)
                {
                    // logv("缺少客户端，清除数据");
                    int iret = 0;
                    // alarm(1);
                    while (_pipeSize>0&&(iret = read(_pipefd[0], readbuffer, bufferSize))>0)
                    
                    {
                        _pipeSize -= iret;
                        // logv("缺少客户端，清除数据:"+std::to_string(_pipeSize));
                    }
                    // logv("缺少客户端，清除数据 -END");
                }
                
            }
            
            // logv("onRecvDataTerminal - write+"+std::to_string(_clients.size()));
            // 缓存写入客户端
            for (auto i = 0; i < _clients.size(); i++)
            {
                auto iterClient = _clients.begin()+i;
                auto iterPipe = _vecPipeArr.begin()+i;
                
                if (iterPipe->length <= 0)
                {
                    // logv("onRecvDataTerminal - iterPipe+"+std::to_string(iterPipe->length));
                    continue;
                }
                (*iterClient)->UpdateConnectionFlag(1);

                auto iret = splice(iterPipe->pipefd[0], NULL, (*iterClient)->getfd(), NULL, iterPipe->length, SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
                if (iret < 0)
                {
                    logd("error splice to client:"+std::to_string(iret)+",errno="+std::to_string(errno));
                    continue;
                    
                }
                if (iret != iterPipe->length)
                {
                    logd("warn splice to client:"+std::to_string(iret)+"/"+std::to_string(iterPipe->length));
                }
                if (iret>0)
                {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                    // logv("splice to client:"+std::to_string(iret)+"/"+std::to_string(iterPipe->length));
                    iterPipe->length -= iret;
                }
                
            }

            // logd("onRecvDataTerminal - isbreak:"+std::to_string(isbreak));
            if (isbreak)
            {
                // logd("isbreak");
                break;
            }
            
            
        }
    }
    
    int ZWRoom::onDataTerminal(char* data, int dataLength)
    {
        // logd("onDataTerminal:"+std::to_string(dataLength));
        _terminal->UpdateConnectionFlag(_clients.size()>0?1:0);
        for(auto client : _clients)
        {
            if (client->getPlayerSetting().disableData == "1")
            {
                continue;
            }
            
            // LOG_VERBOSE<<"onDataTerminal send data"<<LOG_ENDL;
            auto iret = client->writeData(data, dataLength);
            client->UpdateConnectionFlag(1);
            if (_isPlayback && iret == -3)
            {
                return iret;
            }
        }
        return 0;
    }
    void ZWRoom::onDataError(const std::string& str)
    {
        for(auto client : _clients)
        {
            // LOG_VERBOSE<<"onDataTerminal send data"<<LOG_ENDL;
            client->sendMessage(EErrorCode::MediaDataError,GetErrorMessage(EErrorCode::MediaDataError)+":"+str);
        }
    }
    void ZWRoom::onAudioDataMediaClient(MediaClientConnection* client, BaseProtocol* proto, char* data, int dataLength)
    {
        if (_terminal)
        {
            if (_playerSetting.forward0Copy == "1")
            {
                // 实时对讲，音频直接写，失败数据直接丢失
                write(_terminal->getfd(), data, dataLength);
            }
            else
            {
                _terminal->Write(data, dataLength);
            }
            
        }
    }
    void ZWRoom::onDataMediaClient(MediaClientConnection* client, BaseProtocol* proto, char* data, int dataLength)
    {
        // logd("_isTalkback="+std::to_string(_isTalkback));
        proto->UpdateConnectionFlag(_terminal?1:0);
        if (_isTalkback&&_terminal)
        {
            _terminal->UpdateConnectionFlag(1);
        }
    }
    void ZWRoom::onControlMediaClient(MediaClientConnection* client, BaseProtocol* proto, const ControlSetting& setting)
    {
        if (_isPlayback)
        {
            logd("dragPlaybackTime="+setting.dragPlaybackTime+",remote="+setting.remote+",forwardOrRewind="+setting.forwardOrRewind);
        }
        else
        {
            logd("changeStreamType="+setting.streamType+",closeVideoType="+setting.closeVideoType+",control="+setting.control);
        }
        
        // 如果是停止,实时视频退出自己
        if ((!_isPlayback&&(setting.control=="0"||setting.control=="4")))
        {
            // (_isPlayback&&setting.remote=="2")||
            client->closeConnection("Stop");
            return;
        }

        // 回放时的控制，清除缓存(暂缓清除，后续会去除缓存)
        if (_isPlayback && 
        (setting.remote=="3"||setting.remote=="4"||setting.remote=="5"||setting.remote=="6"))
        {
            if (proto)
            {
                proto->ClearWriteBuffer();
            }
            
            // if (_terminal)
            // {
            //     _terminal->ClearWriteBuffer();
            // }
        }
        
        
        
        auto bret = this->control1078(setting);
        if (!bret)
        {
                LOG_DEBUG<<("DuplicateCommand")<<LOG_ENDL;
            client->sendMessage(EErrorCode::DuplicateCommand);
        }

        if (_isPlayback &&setting.remote=="2"&&_terminal)
        {
            logd("_terminal->Close();");
            _terminal->Close();
        }
        
        // LOG_VERBOSE<<"onControlMediaClient"<<LOG_ENDL;
    }
    void ZWRoom::onExitClient(MediaClientConnection* client, BaseProtocol* proto)
    {
        for (auto iter = _clients.begin(); iter != _clients.end(); iter++)
        {
            if (iter->get() == client)
            {
                 _clients.erase(iter);
                 if (_vecPipeArr.size()>0)
                 {
                    _vecPipeArr.erase(_vecPipeArr.begin()+(iter-_clients.begin()));
                 }
                if (_playerSetting.forward0Copy == "1")
                {
                    logd("client remove epoll!");
                    ZWForwardEpoll::instance()->remove(client->getfd());
                }
                logd("Client exit!");
                break;
            }
        }
        checkEmpty();
    }
    void ZWRoom::onExitTerminal(std::shared_ptr<Rtp808Protocol> rtp)
    {
        if (_terminal == rtp)
        {
            if (_playerSetting.forward0Copy == "1")
            {
                logd("terminal remove epoll!");
                ZWForwardEpoll::instance()->remove(rtp->getfd());
            }
            if (_isPlayback)
            {
                ControlSetting setting;
                setting.remote = "2";
                setting.dragPlaybackTime = "000000000000";
                setting.forwardOrRewind = "0";
                control1078(setting);
            }
            else
            {
                ControlSetting setting;
                setting.streamType = "0";
                setting.closeVideoType = "0";
                setting.control = "0";
                control1078(setting);
            }
            _terminal = nullptr;
            checkEmpty();
        }
    }
    
    void ZWRoom::writeMessageClients(int code, const char* message, int messageLength)
    {
        LOG_VERBOSE<<"writeMessageClient"<<LOG_ENDL;
    }
    void ZWRoom::writeDataClients(char* data, int dataLength)
    {
        LOG_VERBOSE<<"writeMessageClient"<<LOG_ENDL;
    }

    // 1078 指令
    void ZWRoom::onAnswer1078(int num, int result)
    {
        logd("number:"+std::to_string(num));
        auto findret = _commandInfos.find(num);

        if (findret != _commandInfos.end())
        {
            _commandInfos.erase(findret);
            if (result != 0)
            {
                if (!_terminal)
                {
                    for (auto iter = _clients.begin(); iter != _clients.end(); iter++)
                    {
                        (*iter)->sendMessage(EErrorCode::PlayCommandFail, "指令下发失败");
                        // (*iter)->closeConnection("Command timeout!");
                    }
                }
            }
            
        }
    }
    bool ZWRoom::checkCommandExists(const std::string& cmdID, const std::string& subCmdID)
    {
        for(auto iter=_commandInfos.begin();iter!=_commandInfos.end();iter++)
        {
            if (iter->second.CmdID == cmdID && iter->second.CmdSubID == subCmdID)
            {
                return true;
            }
            
        }
        return false;
    }
    bool ZWRoom::control1078(const ControlSetting& setting)
    {
        CommandInfo cinfo;
        cinfo.CmdID = "50002";
        int number = -1;
        if (_isPlayback)
        {
            if (checkCommandExists("50002", setting.remote))
            {
                logd("重复发送指令");
                return false;
            }
            
            auto dragPlaybackTime = setting.dragPlaybackTime;
            if (dragPlaybackTime.length()!=12)
            {
                dragPlaybackTime = "000000000000";
            }
            if (_playerSetting.clientId.size()>0)
            {
                MediaF3Kafka::ControlPlayback(_baseSettingF3, dragPlaybackTime, setting.forwardOrRewind, setting.remote
                    ,_playerSetting.clientId, _playerSetting.monitorId);
                number = 1;
            }
            else
            {
                number = MediaF3Protocol::ControlPlayback(_baseSettingF3, dragPlaybackTime, setting.forwardOrRewind, setting.remote);
            }
            cinfo.CmdSubID = setting.remote;
        }
        else
        {
            if (checkCommandExists("50002", setting.control))
            {
                logd("重复发送指令");
                return false;
            }
            if (_playerSetting.clientId.size()>0)
            {
                MediaF3Kafka::ControlRealTime(_baseSettingF3, setting.streamType, setting.closeVideoType, setting.control
                    ,_playerSetting.clientId, _playerSetting.monitorId);
                number = 1;
            }
            else
            {
                number = MediaF3Protocol::ControlRealTime(_baseSettingF3, setting.streamType, setting.closeVideoType, setting.control);
            }
            cinfo.CmdSubID = setting.control;
        }
        
        if (number>=0)
        {
            cinfo.LastCmdTime = std::chrono::system_clock::now();
            cinfo.LastCmdNumber = number;
            _commandInfos.insert(std::pair<int,CommandInfo>(number,cinfo));
            return true;
        }
        return false;
    }
    int ZWRoom::play1078()
    {
        CommandInfo cinfo;
        cinfo.CmdID = "50001";
        cinfo.CmdSubID = "0";
        if (checkCommandExists("50001", "0"))
        {
            logd("重复发送指令");
            return -1;
        }
        int number = -1;
        if (_playerSetting.clientId.size()>0)
        {
            if (_isPlayback)
            {
                MediaF3Kafka::PlayPlayback(_baseSettingF3,_playerSetting.endTime,_playerSetting.startTime,_playerSetting.forwardOrRewind
                , _playerSetting.remoteMode,_playerSetting.streamType, _playerSetting.storageType
                , _playerSetting.deviceType==DEVICETYPE_YUEBIAO?AppSetting::Instance()->rtpPortSendyb:AppSetting::Instance()->rtpPortSend
                ,_playerSetting.clientId, _playerSetting.monitorId);
            }
            else
            {
                MediaF3Kafka::PlayRealTime(_baseSettingF3,_playerSetting.streamType,_playerSetting.dataType
                ,_playerSetting.deviceType==DEVICETYPE_YUEBIAO?AppSetting::Instance()->rtpPortSendyb:AppSetting::Instance()->rtpPortSend
                ,_playerSetting.clientId, _playerSetting.monitorId);
            }
            number = 1;
        }
        else
        {
            if (_isPlayback)
            {
                number = MediaF3Protocol::PlayPlayback(_baseSettingF3,_playerSetting.endTime,_playerSetting.startTime,_playerSetting.forwardOrRewind, _playerSetting.remoteMode,_playerSetting.streamType, _playerSetting.storageType, _playerSetting.deviceType==DEVICETYPE_YUEBIAO?AppSetting::Instance()->rtpPortSendyb:AppSetting::Instance()->rtpPortSend);
            }
            else
            {
                number = MediaF3Protocol::PlayRealTime(_baseSettingF3,_playerSetting.streamType,_playerSetting.dataType,_playerSetting.deviceType==DEVICETYPE_YUEBIAO?AppSetting::Instance()->rtpPortSendyb:AppSetting::Instance()->rtpPortSend);
            }
        }
        
        
        if (number>=0)
        {
            cinfo.LastCmdTime = std::chrono::system_clock::now();
            cinfo.LastCmdNumber = number;
            _commandInfos.insert(std::pair<int,CommandInfo>(number,cinfo));
            return 0;
        }
        return -2;
    }
    void ZWRoom::checkCommand()
    {
        for(auto iter=_commandInfos.begin();iter!=_commandInfos.end();)
        {
        // 指令超时检测
            auto seconds = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - iter->second.LastCmdTime).count();
            if (seconds>AppSetting::Instance()->f3timeout)
            {
                if (!_terminal)
                {
                    for (auto iter2 = _clients.begin(); iter2 != _clients.end(); iter2++)
                    {
                        (*iter2)->sendMessage(EErrorCode::PlayCommandTimeout, "指令下发超时");
                        // (*iter)->closeConnection("Command timeout!");
                    }
                }
                iter = _commandInfos.erase(iter);
            }
            else
            {
                ++iter;
            }
            
        }
    }
    void ZWRoom::checkPlaying()
    {
        if (_isPlayback && !_terminal && _playerSetting.fragments.size() > 0)
        {
            // 当前相对时间
            auto playerPoint = std::chrono::system_clock::now() - _playerSetting.startTimePointAbs + _playerSetting.startTimePoint;
            for(auto fragment : _playerSetting.fragments)
            {
                if (playerPoint >= fragment.start_point && playerPoint < fragment.end_point)
                {
                    _playerSetting.startTime = fragment.startTime;
                    _playerSetting.endTime = fragment.endTime;
                    play1078();
                    break;
                }
            }
        }
        
    }
    void ZWRoom::checkEmpty()
    {
        
        if (_clients.size()<=0)
        {
            if (_isTalkback||_isPlayback)
            {
                if ((_terminal))
                {
                    logd("_terminal->Close();");
                    _terminal->Close();
                }
            }
        }
        // 终端断开后允许其重连，主要为回放片段时需要；终端&客户端均断开，则关闭房间
        if (_terminal == nullptr && _clients.size()<=0)
        {
            auto iter = std::find(_rooms.begin(), _rooms.end(), shared_from_this());
            if (iter != _rooms.end())
            {
                _rooms.erase(iter);
            }
            // for (auto iter = _clients.begin(); iter != _clients.end(); iter++)
            // {
            //     (*iter)->sendMessage(EErrorCode::TerminalBreak);
            //     (*iter)->closeConnection("终端已断开");
            // }
        }
    }
} // namespace mfs

