//
//  demoNotifyAndCallBackProc.cpp
//  EC_SDK_DEMO
//
//  Created by EC Open support team.
//  Copyright(C), 2018, Huawei Tech. Co., Ltd. ALL RIGHTS RESERVED.
//

#include "stdafx.h"
#include <string>
#include <sstream>
#include "demoNotifyProc.h"
#include "demo.h"
#include "demoBeforeLoginDlg.h"
#include "demoConfListDlg.h"
#include "demoCustomMessage.h"
#include "demoData.h"
#include "demoMainMenuDlg.h"
#include "demoTools.h"
#include "HwmAgentDef.h"
#include "HwmSdkAgent.h"
#include "demoPNRPrivacyDlg.h"

demoNotifyProc::demoNotifyProc(void)
{
}

demoNotifyProc::~demoNotifyProc(void)
{
}

// 查询外部通讯录头像回调函数
void queryContactAvatar(const char* account, const char* thirdAccount, const char* sipNumber, char* avatarPath, int pathLen)
{
    /* 根据用户层自己的逻辑 + account thirdAccount sipNumber 获取到头像图片路径信息并复制到avatarPath char数组内*/
    // 测试使用时，在D:\\picture\\路径下放置一张图片test.png
    errno_t err = strcpy_s(avatarPath, pathLen, "D:\\picture\\test.png");
    if (err != S_OK)
    {
        AfxMessageBox(_T("String Copy Error!"));
    }
}

void demoNotifyProc::OnKickedOut()
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    CString tips = _T("OnKickedOut");
    AfxMessageBox(tips);
    //通知主窗口退出当前界面
    demoMainMenuDlg* dlg = dynamic_cast<demoMainMenuDlg *>(app->m_pCurDlgWnd);
    if (dlg == nullptr) {
        return;
    }
    ::PostMessage(dlg->GetSafeHwnd(), WM_LOGOUT_RESULT, hwmsdk::HWM_COMMON_SUCCESS, NULL);
}

void demoNotifyProc::OnShareState(HwmShareStateInfo *shareStateInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    CString state;
    state.Format(_T("%d"), shareStateInfo->state);
    string nameStr = shareStateInfo->name;
    string numberStr = shareStateInfo->number;
    string monitor = to_string(shareStateInfo->monitor);
    string shareType = to_string(shareStateInfo->shareType);
    string appHandle = to_string((UINT64)(uintptr_t)shareStateInfo->appHandle);
    string tips = "***** OnShareState share= " + CTools::UNICODE2UTF(state.GetString())
        + ", name:" + nameStr.c_str()
        + ", number:" + numberStr.c_str()
        + ", monitor:" + monitor.c_str()
        + ", shareType:" + shareType.c_str()
        + ", appHandle:" + appHandle.c_str()
        + ", stopShareReason:" + to_string(shareStateInfo->stopShareReason);

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnRecvShareState(HwmRecvShareStateInfo *shareStateInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    CString state;
    state.Format(_T("%d"), shareStateInfo->state);
    string nameStr = shareStateInfo->name;
    string numberStr = shareStateInfo->number;
    string tips = "***** OnRecvShareState state= " + CTools::UNICODE2UTF(state.GetString())
        + ", name:" + nameStr.c_str() 
        + ", number:" + numberStr.c_str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnConfInfo(HwmConfInfo *confInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if ((app == nullptr) || (confInfo == NULL))
    {
        //窗口已经关闭
        return;
    }

    demoData::GetInstance().SetConfInfo(*confInfo);

    ostringstream role;
    role << confInfo->role;
    CString isOtherCorpConf;
    isOtherCorpConf.Format(_T("%d"), confInfo->isOtherCorpConf);
    CString isInBreakoutSubConf;
    isInBreakoutSubConf.Format(_T("%d"), confInfo->isInBreakoutSubConf);
    string tips = string("***** OnConfInfo confUrl= ") + confInfo->url
        + ", confId:" + confInfo->confId
        + ", confRole:" + role.str()
        + ", chairmanPwd:" + confInfo->chairmanPwd
        + ", generalPwd:" + confInfo->generalPwd
        + ", subject:" + confInfo->subject
        + ", startTimeStamp:" + std::to_string(confInfo->startTimeStamp)
        + ", endTimeStamp:" + std::to_string(confInfo->endTimeStamp)
        + ", isOtherCorpConf:" + CTools::UNICODE2UTF(isOtherCorpConf.GetString())
        + ", isInBreakoutSubConf:" + CTools::UNICODE2UTF(isInBreakoutSubConf.GetString())
        +", customData: " + confInfo->customInfo;
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnConfState(HwmConfStateInfo *confStateInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    CString str;
    str.Format(_T("%d"), confStateInfo->state);
    CString reason;
    reason.Format(_T("%d"), confStateInfo->reason);
    std::string errMsg = CTools::GetErrMsg(confStateInfo->reason);
    string tips = "***** OnConfState state= " + CTools::UNICODE2UTF(str.GetString())
        + ", reason:"+ CTools::UNICODE2UTF(reason.GetString()) + ", errMsg = " + errMsg;
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnRemoteControlState(HwmRemoteControlStateInfo *remoteControlStateInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }
    CString state;
    state.Format(_T("%d"), remoteControlStateInfo->state);
    string nameStr = remoteControlStateInfo->name;
    string numberStr = remoteControlStateInfo->number;
    string tips = "***** OnRemoteControlState state:" + CTools::UNICODE2UTF(state.GetString())
        + ", name:" + nameStr.c_str() 
        + " number:" + numberStr.c_str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnBeRemoteControledState(HwmRemoteControlStateInfo *remoteControlStateInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }
    CString state;
    state.Format(_T("%d"), remoteControlStateInfo->state);
    string nameStr = remoteControlStateInfo->name;
    string numberStr = remoteControlStateInfo->number;
    string tips = "***** OnBeRemoteControledState state= " + CTools::UNICODE2UTF(state.GetString())
        + ", name:" + nameStr.c_str() 
        + " number:" + numberStr.c_str();

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnClickInjectBtn(HwmClickInjectBtn injectBtn, void* data, const char* id)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }
    CString btnCstr;
    btnCstr.Format(_T("%d"), injectBtn);
    string tips = "***** OnClickInjectBtn btn= " + CTools::UNICODE2UTF(btnCstr.GetString());
    if ((injectBtn == HWM_CLICK_INJECT_BTN_CALL_OTHER_NUM || injectBtn == HWM_CLICK_INJECT_BTN_PARTICIPANT_DETAIL) && data != nullptr)
    {
        HwmConfAttendee *attendee = (HwmConfAttendee*)data;
        string nameStr = attendee->name;
        string numberStr = attendee->number;
        string userIdStr = attendee->thirdUserId;
        string accountId = attendee->accountId;
        tips = tips + ", name:" + nameStr.c_str()
            + ", number:" + numberStr.c_str()
            + ", userId:" + userIdStr.c_str()
            + ", accountId:" + accountId.c_str()
            + ", extendedField:" + std::string(attendee->extendedField)
            + ", orgId:" + std::string(attendee->orgId);
            + ", left:" + std::to_string(attendee->posInfo.left)
            + ", top:" + std::to_string(attendee->posInfo.top)
            + ", width:" + std::to_string(attendee->posInfo.width)
            + ", height:" + std::to_string(attendee->posInfo.height);
    }
    else if (injectBtn == HWM_TOOLS_INJECT_BTN_CUSTOM && id != nullptr && data != nullptr)
    {
        string nameStr(id);
        tips = tips + ", id:" + nameStr.c_str();

        HwmCustomBtnInjectInfo* customBtnInfo = (HwmCustomBtnInjectInfo*)data;
        ostringstream left;
        left << customBtnInfo->posInfo.left;
        ostringstream top;
        top << customBtnInfo->posInfo.top;
        ostringstream width;
        width << customBtnInfo->posInfo.width;
        ostringstream height;
        height << customBtnInfo->posInfo.height;
        tips = tips + ", left:" + left.str()
            + ", top:" + top.str()
            + ", width:" + width.str()
            + ", height:" + height.str();
    }
    else if (injectBtn == HWM_CLICK_INJECT_BTN_INVITE && data != nullptr)
    {
        HwmInviteBtnInjectInfo *inviteInfo = (HwmInviteBtnInjectInfo*)data;
        bool isInviteWndOnTop = inviteInfo->isInviteWndOnTop;
        ostringstream state;
        state << isInviteWndOnTop;
        tips = tips + ", isInviteWndOnTop:" + state.str();
    }
    else if (injectBtn == HWM_CLICK_INJECT_BTN_RECALL && data != nullptr)
    {
        HwmConfAttendee *recallInfo = (HwmConfAttendee*)data;
        std::string name = recallInfo->name;
        std::string number = recallInfo->number;
        std::string thirdUserId = recallInfo->thirdUserId;
        std::string accountId = recallInfo->accountId;
        std::string extendedField = recallInfo->extendedField;
        std::string orgId = recallInfo->orgId;
        tips = tips + ", name: " + name
            + ", number: " + number
            + ", thirdUserId: " + thirdUserId
            + ", accountId: " + accountId
            + ", extendedField: " + extendedField
            + ", orgId: " + orgId;
    }
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnCallIncoming(const HwmCallIncomingInfo * callIncomingInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if ((app == nullptr) || (callIncomingInfo == nullptr))
    {
        //窗口已经关闭
        return;
    }

    string numberStr = callIncomingInfo->number;
    string nameStr = callIncomingInfo->name;

    CString callType;
    callType.Format(_T("%d"), callIncomingInfo->callType);
    CString callId;
    callId.Format(_T("%d"), callIncomingInfo->callId);

    string tips = "***** OnCallIncoming callType:" + CTools::UNICODE2UTF(callType.GetString())
        + ", number:" + numberStr.c_str()
        + ", name:" + nameStr.c_str() 
        + ", callId:" + CTools::UNICODE2UTF(callId.GetString());

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnCallState(const HwmCallStateInfo *callStateInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if ((app == nullptr) || (callStateInfo == nullptr))
    {
        //窗口已经关闭
        return;
    }

    CString state;
    state.Format(_T("%d"), callStateInfo->state);
    CString callId;
    callId.Format(_T("%d"), callStateInfo->callId);

    string tips = "***** OnCallState state:" + CTools::UNICODE2UTF(state.GetString())
        + ", callId:" + CTools::UNICODE2UTF(callId.GetString());
    CTools::OutputRetStr(tips);

}

void demoNotifyProc::OnCallInfo(const HwmCallInfo *callInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if ((app == nullptr) || (callInfo == nullptr))
    {
        //窗口已经关闭
        return;
    }

    CString callType;
    callType.Format(_T("%d"), callInfo->callType);

    string number = callInfo->number;
    string name = callInfo->name;
    string startTime = callInfo->startTime;
    string endTime = callInfo->endTime;

    CString isCallOut;
    isCallOut.Format(_T("%d"), callInfo->isCallOut);
    CString callId;
    callId.Format(_T("%d"), callInfo->callId);

    string tips = "***** OnCallInfo callType:" + CTools::UNICODE2UTF(callType.GetString())
        + ", number:" + number.c_str()
        + ", name:" + name.c_str() 
        + ", startTime:" + startTime.c_str()
        + ", endTime:" + endTime.c_str() 
        + ", isCallOut:" + CTools::UNICODE2UTF(isCallOut.GetString())
        + ", callId:" + CTools::UNICODE2UTF(callId.GetString());
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnCallRecordInfo(const HwmCallRecordInfo *callRecordInfo)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if ((app == nullptr) || (callRecordInfo == nullptr))
    {
        //窗口已经关闭
        return;
    }

    CString reason;
    reason.Format(_T("%d"), callRecordInfo->reason);

    CString callType;
    callType.Format(_T("%d"), callRecordInfo->callInfo.callType);

    string number = callRecordInfo->callInfo.number;
    string name = callRecordInfo->callInfo.name;
    string startTime = callRecordInfo->callInfo.startTime;
    string endTime = callRecordInfo->callInfo.endTime;

    CString isCallOut;
    isCallOut.Format(_T("%d"), callRecordInfo->callInfo.isCallOut);
    CString callId;
    callId.Format(_T("%d"), callRecordInfo->callInfo.callId);

    string tips = "***** OnCallRecordInfo reason:" + CTools::UNICODE2UTF(reason.GetString())
        + ", callType:" + CTools::UNICODE2UTF(callType.GetString())
        + ", number:" + number.c_str() 
        + ", name:" + name.c_str() 
        + ", startTime:" + startTime.c_str() 
        + ", endTime:" + endTime.c_str()
        + ", isCallOut:" + CTools::UNICODE2UTF(isCallOut.GetString())
        + ", callId:" + CTools::UNICODE2UTF(callId.GetString());

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnShowExternalConfInfoWnd(int left, int top)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (nullptr == app)
    {
        //窗口已经关闭
        return;
    }

    //通知主窗口退出
    demoMainMenuDlg* dlg = dynamic_cast<demoMainMenuDlg *>(app->m_pCurDlgWnd);
    if (dlg == nullptr) {
        return;
    }

    CPoint* pt = new(std::nothrow) CPoint;
    if (pt == nullptr)
    {
        return;
    }
    pt->SetPoint(left,top);
    ::PostMessage(dlg->GetSafeHwnd(), WM_SHOW_EXTERNAL_CONF_INFO_WND, (WPARAM)pt, NULL);
}

void demoNotifyProc::OnDestroyExternalConfInfoWnd()
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    //通知主窗口退出
    demoMainMenuDlg* dlg = dynamic_cast<demoMainMenuDlg *>(app->m_pCurDlgWnd);
    if (dlg == nullptr) {
        return;
    }

    ::PostMessage(dlg->GetSafeHwnd(), WM_DESTROY_EXTERNAL_CONF_INFO_WND, NULL, NULL);
}

void demoNotifyProc::OnQueryContactAvatar(const char account[HWM_MAX_ACCOUNT_LEN], const char thirdUserId[HWM_MAX_ACCOUNT_LEN], const char sipNumber[HWM_MAX_NUMBER_LEN], char* avatarPath, int pathLen)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if ((app == nullptr) || (strlen(account) == 0 && strlen(thirdUserId) == 0 && strlen(sipNumber) == 0))
    {
        //窗口已经关闭或数据为空
        return;
    }

    string sAccount = account;
    string sThirdUserId = thirdUserId;
    string sSipNumber = sipNumber;


    /* 根据用户层自己的逻辑 + account thirdUserId sipNumber 获取到头像图片路径信息并复制到avatarPath char数组内*/
    // 测试使用时，在D:\\picture\\路径下放置一张图片test.png
    errno_t err = strcpy_s(avatarPath, pathLen, "D:\\picture\\test.png");
    if (err != S_OK)
    {
        AfxMessageBox(_T("String Copy Error!"));
    }

    string tips = "***** OnQueryContactAvatar account:" + sAccount
        + ", thirdUserId:" + sThirdUserId.c_str()
        +", sSipNumber:" + sSipNumber.c_str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnConfList(HwmConflistUpdateType updateType, const HwmConfListInfo* confInfoList,
        unsigned confInfoLen)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    string tips = "***** OnConfList ";
    if (updateType == CONFLIST_UPDTAE_ALL)
    {
        demoData::GetInstance().UpdateConfList(std::vector<HwmConfListInfo>(confInfoList, confInfoList + confInfoLen));
    }
    else
    {
        auto oldList = demoData::GetInstance().GetConfList();
        for (auto pointer = confInfoList; pointer - confInfoList < confInfoLen; pointer++)
        {
             for(auto it = oldList.begin(); it != oldList.end(); ++it)
            {
                if(strcmp(it->confId, pointer->confId) == 0)
                {
                    oldList.erase(it);
                    break;
                }
            }
        }
        
        if (updateType == CONFLIST_UPDATE_ADD)
        {
            oldList.insert(oldList.end(), confInfoList, confInfoList + confInfoLen);
            tips += ": add conf success";
        }
        else if (updateType == CONFLIST_UPDATE_DELETE)
        {
            tips += ": delete conf success";
        }
        demoData::GetInstance().UpdateConfList(oldList);
    }
    
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnAuthenticateExpired(unsigned int reason)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }
    CString reasonStr;
    reasonStr.Format(_T("%d"), reason);
    std::string errMsg = CTools::GetErrMsg(reason);
    string tips = "***** OnAuthenticateExpired reason= " + CTools::UNICODE2UTF(reasonStr.GetString()) + ",errMsg = " + errMsg;
    CTools::OutputRetStr(tips);
    //通知主窗口退出当前界面
    demoMainMenuDlg* dlg = dynamic_cast<demoMainMenuDlg *>(app->m_pCurDlgWnd);
    if (dlg == nullptr) {
        return;
    }
    ::PostMessage(dlg->GetSafeHwnd(), WM_LOGOUT_RESULT, hwmsdk::HWM_COMMON_SUCCESS, NULL);
}

void demoNotifyProc::OnAVDeviceCtrlStateChanged(HwmDeviceType deviceType, bool isOpen)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    ostringstream type;
    type << deviceType;
    ostringstream state;
    state << isOpen;

    string tips = "***** OnAVDeviceCtrlStateChanged deviceType = " + type.str()
        + ", isOpen = " + state.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnAudioFrameNotify(const AudioFrameData * pFrame)
{
    if(nullptr != pFrame)
    {
        FILE* recordFile = nullptr;
        std::string Path = "D:\\AudioFrame.pcm";
        auto error = fopen_s(&recordFile,Path.c_str(), "ab+");
        if (error != 0)
        {
            CTools::OutputRetStr("open file error = " + std::to_string(error));
        }

        if (nullptr != recordFile)
        {
            fwrite(pFrame->pBuffer, sizeof(char), pFrame->iSamples * pFrame->iBytesPerSample * pFrame->iChannels, recordFile);
            fclose(recordFile);
        }
    }
}

void demoNotifyProc::OnConfIsShareLockedChanged(bool  isShareLocked)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    ostringstream state;
    state << isShareLocked;

    string tips = "***** OnConfIsShareLockedChanged isShareLocked = " + state.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnRefreshPairCode(HwmPairCodeInfo* data)
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    if(data != nullptr)
    {
        string tips = data->pairCode;
        tips = "***** OnRefreshPairCode pairCode= " + tips;
        CTools::OutputRetStr(tips);
    }
}

void demoNotifyProc::OnCorpConfig(HwmCorpConfigInfo* data)
{
    ostringstream enablePstn;
    enablePstn << data->enablePstn;
    string tips = "***** OnCorpConfig enablePstn= " + enablePstn.str();
    CTools::OutputRetStr(tips);

    demoData::GetInstance().SetHasRecordPermission(data->enableRecord);
    demoData::GetInstance().SetIsSmsEnable(data->enableSms);
    demoData::GetInstance().SetCorpEnableSummary(data->corpEnableSummary);
}

void demoNotifyProc::OnUserCorpInfo(HwmUserCorpInfoNotifyType type)
{
    ostringstream osType;
    osType << type;
    string tips = "***** OnUserCorpInfo type = " + osType.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnSdkDisconnected()
{
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (app == nullptr)
    {
        //窗口已经关闭
        return;
    }

    CString tips = _T("OnSdkDisconnected");
    AfxMessageBox(tips);
    //通知主窗口退出
    demoMainMenuDlg* dlg = dynamic_cast<demoMainMenuDlg *>(app->m_pCurDlgWnd);
    if (dlg == nullptr) {
        return;
    }
    ::PostMessage(dlg->GetSafeHwnd(), WM_LOGOUT_RESULT, hwmsdk::HWM_COMMON_SUCCESS, NULL);
}


void demoNotifyProc::OnConfIncoming(HwmConfIncomingInfo* data)
{
    ostringstream printInfo;
    printInfo << "mediaType = " << data->mediaType
              << ", state = " << data->state
              << ", confId = " << data->confId
              << ", vmrId = " << data->vmrId
              << ", isP2PConf = " << data->isP2PConf
              << ", thirdUserId = " << data->thirdUserId
              << ", invitorName = " << data->invitorName
              << ", invitorOrgId = " << data->invitorOrgId
              << ", schedulerName = " << data->schedulerName
              << ", schedulerAliasCN = " << data->schedulerAliasCN
              << ", schedulerAliasEN = " << data->schedulerAliasEN;

    string tips = "***** OnConfIncoming " + printInfo.str();

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnRenderWindowInfoList(const HwmHwndListInfo* hwndInfo)
{
    demoData::GetInstance().SetWindowHandleInfo(WM_WINDLE_HANDLE_NOTIFY, *hwndInfo);
}

void demoNotifyProc::OnConfEndedNotify(const HwmConfEndInfo * confEndInfo)
{
    if (confEndInfo == nullptr)
    {
        return;
    }
    ostringstream state;
    state << confEndInfo->reason;
    std::string errMsg = CTools::GetErrMsg(confEndInfo->reason);
    string tips = "***** OnConfEndedNotify reason= " + state.str() + ", errMsg = " + errMsg;

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnPoorNetworkQualityInfoNotify(const HwmPoorNetWorkQualityInfo * poorNetWorkInfo)
{
    if (poorNetWorkInfo == nullptr)
    {
        return;
    }
    ostringstream info;
    info << "name: " << poorNetWorkInfo->nickName;
    string tips = "***** OnPoorNetworkQualityInfoNotify " + info.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnShowVoiceprintStatement(const HwmShowVoiceprintStatementInfo* info)
{
    if (info == nullptr)
    {
        return;
    }
    demoPNRPrivacyDlg dlg;
    dlg.SetEntry(info->entry);
    INT_PTR nResponse = dlg.DoModal();
}

void demoNotifyProc::OnSpeakerListChanged(const HwmSpeakerList* speakerList)
{
    if (speakerList == nullptr)
    {
        return;
    }
    
    ostringstream speakerSize;
    speakerSize << speakerList->speakerSize;
    ostringstream speakers;
    for (UINT i = 0; i < speakerList->speakerSize; i++)
    {
        speakers << ",name: " << speakerList->speakers[i].name;
        speakers << ",userId: " << speakerList->speakers[i].userId;
    }
    string tips = "***** OnSpeakerListChanged size: " + speakerSize.str() + speakers.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnVideoStreamTypeChanged(const HwmVideoStreamTypeInfo* videoStreamTypeInfo)
{
    if (videoStreamTypeInfo == nullptr)
    {
        return;
    }
    ostringstream userId;
    userId << "userId: " << videoStreamTypeInfo->userId;
    ostringstream streamType;
    streamType << "streamType: " << videoStreamTypeInfo->streamType;
    string tips = "***** OnVideoStreamTypeChanged " + userId.str() + "," + streamType.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnAnnotationStateChanged(const HwmAnnotationStateInfo* stateInfo)
{
    if (stateInfo == nullptr)
    {
        return;
    }
    ostringstream annoState;
    annoState << "annoState: " << stateInfo->annotationState;
    string tips = "***** HwmAnnotationStateInfo " + annoState.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnVideoAttendeeListChanged()
{
    string tips = "***** OnVideoAttendeeListChanged ";
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnMeetingInfoChanged(const HwmMeetingInfo* meetingInfo)
{
    if (meetingInfo == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "confId = " << meetingInfo->baseInfo.confId << ", vmrConfId = " << meetingInfo->baseInfo.vmrConfId
        <<", confSubject = " << meetingInfo->baseInfo.confSubject << ", selfConfRole = " << meetingInfo->baseInfo.selfConfRole
        << ", hostPwd = " << meetingInfo->baseInfo.hostPwd << ", hostJoinUri = " << meetingInfo->baseInfo.hostJoinUri
        << ", guestPwd = " << meetingInfo->baseInfo.guestPwd << ", guestJoinUri = " << meetingInfo->baseInfo.guestJoinUri
        << ", audiencePwd = " << meetingInfo->baseInfo.audiencePwd << ", audienceJoinUri = " << meetingInfo->baseInfo.audienceJoinUri
        << ", startTimeStamp = " << meetingInfo->baseInfo.startTimeStamp << ", endTimeStamp = " << meetingInfo->baseInfo.endTimeStamp
        << ", corpEnableWatermark = " << meetingInfo->baseInfo.corpEnableWatermark << ", corpEnableForbidScreenShots = " << meetingInfo->baseInfo.corpEnableForbidScreenShots;
     
    string tips = "***** OnMeetingInfoChanged " + printInfo.str();

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnAddAttendeeNotify(const HwmAddAttendeeResultList* addAttendeeResultList)
{
    if (addAttendeeResultList == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "***** OnAddAttendeeNotify size: " << addAttendeeResultList->addAttendeeResultSize << ", [";
    for (UINT i = 0; i < addAttendeeResultList->addAttendeeResultSize; i++)
    {
        if(i > 0)
        {
            printInfo << " , ";
        }

        printInfo << "{ number: " << addAttendeeResultList->addAttendeeResults[i].number;
        printInfo << ", resultCode: " << addAttendeeResultList->addAttendeeResults[i].resultCode;
        printInfo << ", thirdUserId: " << addAttendeeResultList->addAttendeeResults[i].thirdUserId;
        printInfo << ", orgId: " << addAttendeeResultList->addAttendeeResults[i].orgId;
        printInfo << " }";
    }
    printInfo << "]";
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnWaitingListChanged(const HwmAttendeeListInfo* waitingList)
{
    if (waitingList == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "***** OnWaitingListChanged size: " << waitingList->numOfAttendee << ", [";
    for (UINT i = 0; i < waitingList->numOfAttendee; i++)
    {
        if (i > 0)
        {
            printInfo << " , ";
        }

        printInfo << "{ number: " << waitingList->attendees[i].number;
        printInfo << ", name: " << waitingList->attendees[i].name;
        printInfo << ", aliasCN: " << waitingList->attendees[i].aliasCN;
        printInfo << ", aliasEN: " << waitingList->attendees[i].aliasEN;
        printInfo << ", extendedField: " << waitingList->attendees[i].extendedField;
        printInfo << ", email: " << waitingList->attendees[i].email;
        printInfo << ", sms: " << waitingList->attendees[i].sms;
        printInfo << ", isMute: " << waitingList->attendees[i].isMute;
        printInfo << ", isAutoInvite: " << waitingList->attendees[i].isAutoInvite;
        printInfo << ", role: " << waitingList->attendees[i].role;
        printInfo << ", type: " << waitingList->attendees[i].type;
        printInfo << ", thirdUserId: " << waitingList->attendees[i].thirdUserId;
        printInfo << ", userUuid: " << waitingList->attendees[i].userUuid;
        printInfo << ", callStatus: " << waitingList->attendees[i].callStatus;
        printInfo << ", isAnonymous: " << waitingList->attendees[i].isAnonymous;
        printInfo << ", orgId: " << waitingList->attendees[i].orgId;
        printInfo << ", accountId: " << waitingList->attendees[i].accountId;
        printInfo << ", isSelf: " << waitingList->attendees[i].isSelf;
        printInfo << ", isCollaborator: " << waitingList->attendees[i].isCollaborator;
        printInfo << ", userId: " << waitingList->attendees[i].userId;
        printInfo << " }";
    }
    printInfo << "]";
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnSelfLocalRecordStateNotify(const HwmLocalRecordStateInfo * localRecordStateInfo)
{
    if (localRecordStateInfo == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "***** OnSelfLocalRecordStateNotify status = " << localRecordStateInfo->status << ", localRecordPath = " << localRecordStateInfo->localRecordPath
        << "startTime = " << localRecordStateInfo->startTime;
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnUserSavePathChanged(const HwmUserSavePathInfo * userSavePathInfo)
{
    if (userSavePathInfo == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "***** OnUserSavePathChanged path type = " << userSavePathInfo->pathType << ", path = " << userSavePathInfo->path;
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnDoubleClickParticipantListItemNotify(const HwmParticipantItemInfo * participantInfo)
{
    if (participantInfo == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "***** OnDoubleClickParticipantListItemNotify number = " << participantInfo->number << ", name = " << participantInfo->nickName;
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnAttendeeListChanged(const HwmAttendeeListInfo* attendeeList)
{
    if (attendeeList == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "***** OnAttendeeListChanged size: " << attendeeList->numOfAttendee << ", [";
    for (UINT i = 0; i < attendeeList->numOfAttendee; i++)
    {
        if (i > 0)
        {
            printInfo << " , ";
        }

        printInfo << "{ number: " << attendeeList->attendees[i].number;
        printInfo << ", name: " << attendeeList->attendees[i].name;
        printInfo << ", aliasCN: " << attendeeList->attendees[i].aliasCN;
        printInfo << ", aliasEN: " << attendeeList->attendees[i].aliasEN;
        printInfo << ", extendedField: " << attendeeList->attendees[i].extendedField;
        printInfo << ", email: " << attendeeList->attendees[i].email;
        printInfo << ", sms: " << attendeeList->attendees[i].sms;
        printInfo << ", isMute: " << attendeeList->attendees[i].isMute;
        printInfo << ", isAutoInvite: " << attendeeList->attendees[i].isAutoInvite;
        printInfo << ", role: " << attendeeList->attendees[i].role;
        printInfo << ", type: " << attendeeList->attendees[i].type;
        printInfo << ", thirdUserId: " << attendeeList->attendees[i].thirdUserId;
        printInfo << ", userUuid: " << attendeeList->attendees[i].userUuid;
        printInfo << ", callStatus: " << attendeeList->attendees[i].callStatus;
        printInfo << ", isAnonymous: " << attendeeList->attendees[i].isAnonymous;
        printInfo << ", orgId: " << attendeeList->attendees[i].orgId;
        printInfo << ", accountId: " << attendeeList->attendees[i].accountId;
        printInfo << ", isSelf: " << attendeeList->attendees[i].isSelf;
        printInfo << ", isCollaborator: " << attendeeList->attendees[i].isCollaborator;
        printInfo << ", userId: " << attendeeList->attendees[i].userId;
        printInfo << " }";
    }
    printInfo << "]";
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnSubtitleStateChanged(bool isOpen)
{
    ostringstream printInfo;
    printInfo << "isOpen = " << isOpen ;
    string tips = "***** OnSubtitleStateChanged " + printInfo.str();

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnWaitingRoomStateChanged(bool isOpen)
{
    ostringstream printInfo;
    printInfo << "isOpen = " << isOpen;
    string tips = "***** OnWaitingRoomStateChanged " + printInfo.str();

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnRealTimeSubtitleInfoNotify(const HwmRealTimeSubtitleInfo* realTimeSubtitleInfo)
{
    if (realTimeSubtitleInfo == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "{ userId: "            << realTimeSubtitleInfo->userId,
    printInfo << ", originalMsg: "       << realTimeSubtitleInfo->originalMsg,
    printInfo << ", translatedMsg: "     << realTimeSubtitleInfo->translatedMsg,
    printInfo << ", isFinal: "           << realTimeSubtitleInfo->isFinal,
    printInfo << ", name: "              << realTimeSubtitleInfo->name,
    printInfo << ", aliasCN: "           << realTimeSubtitleInfo->aliasCN;
    printInfo << ", aliasEN: "           << realTimeSubtitleInfo->aliasEN;
    printInfo << ", isExistVoicePrint: " << realTimeSubtitleInfo->isExistVoicePrint;
    printInfo << ", isRecognize: "       << realTimeSubtitleInfo->isRecognize;
    printInfo << ", speakerCN: "         << realTimeSubtitleInfo->speakerCN;
    printInfo << ", speakerEN: "         << realTimeSubtitleInfo->speakerEN;
    printInfo << ", userCN: "            << realTimeSubtitleInfo->userCN;
    printInfo << ", userEN: "            << realTimeSubtitleInfo->userEN;
    printInfo << ", tag: "               << realTimeSubtitleInfo->tag;
    printInfo << ", isExistVoicePrint: " << realTimeSubtitleInfo->translateLanguage;
    printInfo << " }";

    string tips = "***** OnRealTimeSubtitleInfoNotify " + printInfo.str();
    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnSubtitleRecordNotify(const HwmSubtitleRecordInfo* subtitleRecordInfo)
{
    if (subtitleRecordInfo == nullptr)
    {
        return;
    }
    ostringstream printInfo;
    printInfo << "{ timeStamp: " << subtitleRecordInfo->timeStamp,
    printInfo << ", msgId: "     << subtitleRecordInfo->msgId,
    printInfo << " }";

    string tips = "***** OnSubtitleRecordNotify " + printInfo.str();
    CTools::OutputRetStr(tips);
    OnRealTimeSubtitleInfoNotify(&subtitleRecordInfo->realTimeSubtitleInfo);
}

void demoNotifyProc::OnP2PConfRecordNotify(HwmP2PConfRecordInfo * recordInfo)
{
    if (recordInfo == nullptr)
    {
        return;
    }
    ostringstream resultCode;
    resultCode << recordInfo->resultCode;
    std::string errMsg = CTools::GetErrMsg(recordInfo->resultCode);
    string isCallOut = to_string(recordInfo->isCallOut);
    string mediaType = to_string(recordInfo->mediaType);
    string isCallEstablished = to_string(recordInfo->isCallEstablished);
    HwmCallMemberInfo callerInfo = recordInfo->callerInfo;
    HwmCallMemberInfo calleeInfo = recordInfo->calleeInfo;
    string tips = "***** OnP2PConfRecordNotify resultCode= " + resultCode.str() + "\r\n"
        + " startTimeStamp= " + std::to_string(recordInfo->startTimeStamp) + "\r\n"
        + " endTimeStamp= " + std::to_string(recordInfo->endTimeStamp) + "\r\n"
        + " isCallOut= " + isCallOut.c_str() + "\r\n"
        + " mediaType= " + mediaType.c_str() + "\r\n"
        + " resultMsg= " + std::string(recordInfo->resultMsg) + "\r\n"
        + " errMsg = " + errMsg + "\r\n"
        + " isCallEstablished= " + isCallEstablished.c_str() + "\r\n"
        + " callerInfo: {" + "\r\n"
        + "   number= " + callerInfo.number + "\r\n"
        + "   nickName= " + callerInfo.nickName + "\r\n"
        + "   uuid= " + callerInfo.userUuid + "\r\n"
        + "   thirdUserId= " + callerInfo.thirdUserId + "\r\n"
        + "   orgId= " + callerInfo.orgId + "\r\n"
        + "}" + "\r\n"
        + " calleeInfo: {" + "\r\n"
        + "   number= " + calleeInfo.number + "\r\n"
        + "   nickName= " + calleeInfo.nickName + "\r\n"
        + "   uuid= " + calleeInfo.userUuid + "\r\n"
        + "   thirdUserId= " + calleeInfo.thirdUserId + "\r\n"
        + "   orgId= " + calleeInfo.orgId + "\r\n"
        + "}";

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnStartLocalRecordOperationInterruptNotify(const HwmInterruptInfo * info)
{
    if (info == nullptr)
    {
        return;
    }

    std::string typeStr = "SELECT_SAVE_PATH";
    switch (info->type)
    {
    case RISK_TIP:
        typeStr = "RISK_TIP";
        break;
    case INFLUENCE_RECORD_FOR_GALLERY:
        typeStr = "INFLUENCE_RECORD_FOR_GALLERY";
        break;
    case SAVE_PATH_NOT_WRITEABLE:
        typeStr = "SAVE_PATH_NOT_WRITEABLE";
        break;
    case SAVE_TEMP_RECORD_FILE:
        typeStr = "SAVE_TEMP_RECORD_FILE";
        break;
    case HDCLOUD_PERFORMANCE_CONSUMPTION:
        typeStr = "HDCLOUD_PERFORMANCE_CONSUMPTION";
        break;
    case NO_SPEAKER_DEVICE:
        typeStr = "NO_SPEAKER_DEVICE";
        break;
    default:
        break;
    }
    string tips = "***** OnStartLocalRecordOperationInterruptNotify, type = " + typeStr;

    CTools::OutputRetStr(tips);
}

void demoNotifyProc::OnCreateConfFinishedNotify(hwmsdk::HwmErrCode ret, const char * reason, HwmCreateConfResult * confInfo)
{
    ostringstream retStream;
    retStream << ret;
    string msgStr = reason != nullptr ? reason : "";
    string confId = confInfo != nullptr ? confInfo->confId : "";
    string tips = "----- OnCreateConfFinishedNotify= " + retStream.str() + ", msg= " + msgStr.c_str();
    if (confInfo != NULL)
    {
        tips = tips + ", confId= " + confInfo->confId;
        tips = tips + ", url= " + confInfo->guestJoinUri;
        tips = tips + ", hostPwd= " + confInfo->hostPwd;
        tips = tips + ", guestPwd= " + confInfo->guestPwd;
        tips = tips + ", confRole= " + std::to_string(confInfo->selfConfRole);
        tips = tips + ", startTime= " + std::to_string(confInfo->startTime);
        tips = tips + ", endTime= " + std::to_string(confInfo->endTime);
        tips = tips + ", startTimeStamp= " + std::to_string(confInfo->startTimeStamp);
        tips = tips + ", endTimeStamp= " + std::to_string(confInfo->endTimeStamp);
        tips = tips + ", confSubject= " + confInfo->subject;
        tips = tips + ", schedulerName= " + confInfo->schedulerName;
    }

    CTools::OutputRetStr(tips);

    CTools::ShowErrMsg(ret, reason);
}

void demoNotifyProc::OnLoginStateChangeNotify(const HwmLoginStateInfo* loginStateInfo)
{
    if (loginStateInfo == nullptr)
    {
        return;
    }

    ostringstream printInfo;
    printInfo << "***** OnLoginStateChangeNotify loginState = " << loginStateInfo->loginState;
    CTools::OutputRetStr(printInfo.str());
}

void demoNotifyProc::OnConfForbiddenScreenShotsEnableChanged(HwmForbiddenScreenShotsEnableType enableType)
{
    ostringstream printInfo;
    printInfo << "***** OnConfForbiddenScreenShotsEnableChanged enableType = " << enableType;
    CTools::OutputRetStr(printInfo.str());
}