//
//  YCKCallManagerProtocol.h
//  YCKCall
//
//  Created by 徐家骏 on 2019/4/29.
//  Copyright © 2019 徐家骏. All rights reserved.
//

#ifndef YCKCallManagerProtocol_h
#define YCKCallManagerProtocol_h

#pragma once

#ifdef SDK_SIMPLE_INCLUDE
#include "common.h"
#include "YCKGlobalDefs.h"
#include "YCKitExport.h"
#include "NVVideoImageBuffer.h"
#include "YCKVideoFrameContext.h"
#include "YCKDataFrameContext.h"
#include "NVExternalAudioStreamProtocol.h"
#include "NVDefAudioFilterConfig.h"
#include "YCKNetworkInfo.h"
#include "YCKDeviceID.h"
#else
#include <YCKSdwan/common.h>
#include <YCKit/YCKGlobalDefs.h>
#include <YCKit/YCKitExport.h>
#include <YCKit/Video/NVVideoImageBuffer.h>
#include <YCKit/Video/YCKVideoFrameContext.h>
#include <YCKit/Data/YCKDataFrameContext.h>
#include <YCKit/Audio/NVExternalAudioStreamProtocol.h>
#include <YCKit/Audio/NVDefAudioFilterConfig.h>
#include <YCKit/YCKit/YCKDeviceID.h>
#include <YCKSdwan/YCKNetworkInfo.h>
#endif
#include "YCKCallOption.h"
#include "YCKCallInfo.h"
#include "YCKCustomSignal.h"
#include "YCKCallStatus.h"
#include "YCKCallResultInfo.h"
#include <vector>

extern const std::string YCKCallStateChangeNotification;

extern const std::string YCKCallStateIdle;
extern const std::string YCKCallStateCalling;
extern const std::string YCKCallStateCalled;
extern const std::string YCKCallStateIncall;

extern const std::string YCKCallEventInvite;
extern const std::string YCKCallEventAccept;
extern const std::string YCKCallEventReject;
extern const std::string YCKCallEventCancel;
extern const std::string YCKCallEventEnd;
extern const std::string YCKCallEventInviteMember;
extern const std::string YCKCallEventKickMember;

extern const std::string YCKCallEventRecvInvite;
extern const std::string YCKCallEventRecvSidCreated;
extern const std::string YCKCallEventRecvRing;
extern const std::string YCKCallEventRecvServerRing;
extern const std::string YCKCallEventRecvAccept;
extern const std::string YCKCallEventRecvReject;
extern const std::string YCKCallEventRecvCancel;
extern const std::string YCKCallEventRecvBusy;
extern const std::string YCKCallEventRecvEnd;
extern const std::string YCKCallEventRecvMemberState;

extern const std::string YCKCallEventTimeoutCalling;
extern const std::string YCKCallEventTimeoutCalled;

extern const std::string YCKCallEventCallkitActiveAudio;
extern const std::string YCKCallEventCallkitDeactiveAudio;

//多语的key
extern const std::string YCKLocalizedKey_NotificationActionAccept;
extern const std::string YCKLocalizedKey_NotificationActionReject;
extern const std::string YCKLocalizedKey_NotificationMediaAudio;
extern const std::string YCKLocalizedKey_NotificationMediaVideo;
extern const std::string YCKLocalizedKey_NotificationGroupMediaAudio;
extern const std::string YCKLocalizedKey_NotificationGroupMediaVideo;


//NS_ASSUME_NONNULL_END

/**
 *  通话Block
 *
 *  @param error  通话结果, 如果成功error为nil
 */
//typedef void(^YCKCallHandler)(NSError * __nullable error);
typedef std::function<void(int)> YCKCallHandler;

enum YCKSuggestedPlaySound {
    YCKSuggestedPlaySoundStopPlaying = 0,
    YCKSuggestedPlaySoundPeerIncall = 1,
    YCKSuggestedPlaySoundPeerTimeout = 2,
    YCKSuggestedPlaySoundPeerOffline = 3,
    YCKSuggestedPlaySoundPeerBusy = 4,
    YCKSuggestedPlaySoundCalling = 5,
    YCKSuggestedPlaySoundCalled = 6
};

enum YCKRecordType {
    YCKRecordTypeAudio,
    YCKRecordTypeVideo,
    YCKRecordTypeScreen,
};

class DLL_DECL YCKCallManagerDelegate {
public:
    virtual ~YCKCallManagerDelegate() = default;

    virtual void onInvite(int64_t sessionId, int64_t callee) = 0;

    virtual void onCancel(int64_t sessionId, int64_t callee) = 0;

    virtual void onCallingTimeout(int64_t sessionId, int64_t callee) = 0;

    virtual void onReceiveRing(int64_t sessionId, int64_t callee) = 0;

/**
 *  @discussion 主叫收到被叫接听
 *
 *  @param sessionId   session id
 *  @param callee      被叫帐号, 多方呼叫时为 YCKSessionManagerUserId
 */
    virtual void onReceiveAccepted(int64_t sessionId, int64_t callee) = 0;

/**
 *  @discussion 主叫收到被叫拒绝
 *
 *  @param sessionId   session id
 *  @param callee      被叫帐号
 *  @param reasonCode 拒绝理由
 */
    virtual void onReceiveRejected(int64_t sessionId, int64_t callee, int reasonCode) = 0;

/**
 *  @discussion 主叫收到被叫忙
 *
 *  @param sessionId   session id
 *  @param callee      被叫帐号
 */
    virtual void onReceiveBusy(int64_t sessionId, int64_t callee) = 0;

///**
// *  @discussion 主叫收到被叫挂断
// *
// *  @param sessionId   session id
// *  @param callee      被叫帐号
// */
//- (void)onReceiveHanguped:(int64_t)sessionId
//                     from:(int64_t)callee;


/**
 *  @discussion 被叫收到呼叫（振铃）
 *
 *  @param sessionId  session id
 *  @param caller     主叫帐号
 *  @param mediaType  呼叫类型
 */
    virtual void onReceiveInvite(int64_t sessionId, int64_t caller, YCKCallMediaType mediaType, std::string title) = 0;

    virtual void onReceiveCancel(int64_t sessionId, int64_t caller) = 0;

    virtual void onAccept(int64_t sessionId, int64_t caller) = 0;

    virtual void onReject(int64_t sessionId, int64_t caller) = 0;

    virtual void onCalledTimeout(int64_t sessionId, int64_t caller) = 0;

/**
  @discussion 通话建立

 @param sessionId session id
 */
    virtual void onCallEstablished(int64_t sessionId) = 0;

/**
 @discussion 通话结束

 @param sessionId session id
 */
    virtual void onCallEnd(int64_t sessionId, int reasonCode) = 0;
	virtual void onCallEnd(std::shared_ptr<YCKCallResultInfo> resultInfo) = 0;

//    virtual void onMemberStateChange(std::unordered_map<int64_t, shared_ptr<YCKParticipant>> memberState) = 0;
    virtual void onMemberStateChange(std::shared_ptr<json> memberState) = 0;

    virtual void onMemberJoin(const int64_t * members, int size, int64_t sessionId) = 0;

    virtual void onMemberLeave(const int64_t * members, int size, int64_t sessionId) = 0;

    // todo
    virtual void onRemoteVideoFrameReady(std::shared_ptr<NVVideoImageBuffer> image, std::shared_ptr<YCKVideoFrameContext> frameContext, int64_t from) = 0;

    virtual void onLocalVideoFrameReady(std::shared_ptr<NVVideoImageBuffer> image, std::shared_ptr<YCKVideoFrameContext> frameContext) = 0;

    virtual void onReceiveCustomSignal(YCKCustomSignal signal) = 0;


    virtual void onCallStatus(std::shared_ptr<YCKCallStatus> status) = 0;

//    @optional
    virtual void onAudioVolume(int volume, int64_t from) = 0;

    virtual void onAudioVolumeOfSelf(int volume) = 0;

    /**
     * !!NOTE: data will be free after call. using data synchronously, or copy it.
     */
    //virtual void onDataReceived(const byte* data, size_t data_size, std::shared_ptr<YCKDataFrameContext> frameContext, int64_t from) = 0;
	virtual void onAppCommandReceived(const byte* data, size_t data_size, int64_t from) = 0;
	virtual void onAppDataReceived(const byte* data, size_t data_size, int64_t from) = 0;
	
/**
 *  @discussion 自定义信令接收超时
 *
 *  @param uuid   信令对应的uuid
 */
	virtual void onCustomSignalTTLTimeOut(std::string uuid) = 0;

/**
 *  @discussion 自定义信令丢失
 *
 *  @param uuid   信令对应的uuid
 */
	virtual void onCustomSignalLost(std::string uuid) = 0;

//报告通话中的事件，比如对方被系统电话打断，本地或者对方网络不佳，通话中有掉线等
    virtual void onCallEvent(YCKCallEvent event, int64_t from) = 0;

    virtual std::string nameOfCallerWithUid(int64_t uid) = 0;

    virtual std::string phoneNumberOfCallerWithUid(int64_t uid) = 0;

    virtual std::string localizedStringOfKey(std::string key) = 0;

    // todo 可能需要去掉
    virtual void suggestPlaySound(YCKSuggestedPlaySound sound) = 0;

//TODO:还有一些场景需要考虑：1）掉线，2）单向视频或者单向音频，3）自动接听，4）对方被打断的情况，4）单帐号多设备，6）网络质量提示
    virtual void beginRecordForSessionID(int64_t sessionId) = 0;

	virtual void onCameraError(const YCKDeviceId& devId, NVDeviceErrorCode code) = 0;

	virtual void onAudioInputError(const YCKDeviceId& devId, NVDeviceErrorCode code) = 0;

	virtual void onAudioOutputError(const YCKDeviceId& devId, NVDeviceErrorCode code) = 0;
};

class YCKAbstractWhiteboard;

class DLL_DECL YCKCallManagerProtocol {
public:
    virtual ~YCKCallManagerProtocol() = default;

    virtual void prepareDevices(bool& isAudioInSuccess,bool& isAudioOutSuccess, bool& isVideoSuccess,bool startAudioIn)=0;

    virtual void stopDevicesWhenNotInCall()=0;
/**
 *  主叫发起1-1通话
 *
 *  @param callee       被叫帐号
 *  @param mediaType    呼叫媒体类型
 *  @param option       开始通话附带的选项, 可以为空
 *  @param completion   发起通话结果回调
 */
    virtual void callOneOne(int64_t callee, YCKCallMediaType mediaType,
                            std::shared_ptr<YCKCallOption> option, YCKCallHandler completion) = 0;

/**
 *  主叫发起多方通话
 *
 *  @param callees       被叫帐号列表, 可以是nil，包含0-多个被叫帐号
 *  @param mediaType     呼叫媒体类型
 *  @param option        开始通话附带的选项, 可以为空
 *  @param completion    发起通话结果回调
 */
    virtual void callMultiparty(std::vector<int64_t> callees, YCKCallMediaType mediaType,
                                std::shared_ptr<YCKCallOption> option, YCKCallHandler completion) = 0;

/**
 *  加入多方通话，根据他人分享的Session Id加入
 *
 *  @param sessionId    已建立的多方通话Session Id
 *  @param completion   发起通话结果回调
 */
    virtual void joinMultiparty(int64_t sessionId, YCKCallMediaType mediaType,
                                std::shared_ptr<YCKCallOption> option, YCKCallHandler completion) = 0;

/**
 *  邀请加入多方通话，由通话中的成员发起
 *
 *  @param callees       被叫帐号列表, 可以是nil，包含0-多个被叫帐号
 *  @param sessionId     已建立的多方通话Session Id
 *  @param completion    结果回调
 */
    virtual void inviteMultiparty(std::vector<int64_t> callees, int64_t sessionId, YCKCallHandler completion) = 0;

/**
 *  踢出多方通话，由通话中的成员发起
 *
 *  @param callees       被叫帐号列表, 可以是nil，包含0-多个被叫帐号
 *  @param sessionId     已建立的多方通话Session Id
 *  @param completion    结果回调
 */
    virtual void kickMultiparty(std::vector<int64_t> callees, int64_t sessionId, YCKCallHandler completion) = 0;

/**
 *  接听当前呼叫
 *
 */
    virtual void accept() = 0;

/**
 *  拒绝当前呼叫
 *
 */
    virtual void reject() = 0;

/**
 *  取消当前发起的呼出通话
 *
 */
    virtual void cancel() = 0;

    /**
 *  挂断当前通话
 *
 */
    virtual void hangup() = 0;

    //挂断并且结束整个通话
    virtual void hangupAndCloseSession() = 0;

    //virtual void sendData(const std::vector<char>& data, std::shared_ptr<YCKDataFrameContext> frameContext) =0;

	virtual void sendAppCommand(const std::vector<char> & data) = 0;
	virtual void sendAppData(const std::vector<char>& data) = 0;
	//发给单个接收人
	virtual void sendAppCommand(const std::vector<char> & data, int64_t to_uid) = 0;
	virtual void sendAppData(const std::vector<char>& data, int64_t to_uid) = 0;

    virtual void sendCustomSignal(YCKCustomSignal signal, int64_t uid) = 0;

    virtual void requestRecord(YCKRecordType recordType) = 0;

    //todo: 这个要再优化一下 change to getCurrentCallInfo
    virtual std::shared_ptr<YCKCallInfo> getCurrentCallInfo() = 0;

    virtual std::string currentCallState() = 0;

    virtual YCKVideoCameraPosition getCameraPosition() = 0;

    virtual void setCameraPosition(YCKVideoCameraPosition position) = 0;

    virtual uint32_t getVideoAverageBitrate() = 0;

    virtual void setVideoAverageBitrate(uint32_t bitrate) = 0;

    virtual uint32_t getBandwidthUpperLimit() = 0;

    virtual void setBandwidthUpperLimit(uint32_t bitrate) = 0;

    virtual int32_t getVideoFramerate() = 0;

    virtual void setVideoFramerate(int32_t framerate) = 0;

    virtual YCKCallVideoPreset getVideoPreset() = 0;

    virtual void setVideoPreset(YCKCallVideoPreset preset) = 0;

	// 获取/设置最大视频分辨率
	virtual const NVVideoSize& getMaxVideoSize() = 0;
	virtual bool SetMaxVideoSize(const NVVideoSize& size) = 0;

	// 获取/设置视频编码器
	virtual VideoCodecCategory getVideoCodecCategory() = 0;
	virtual bool setVideoCodecCategory(VideoCodecCategory codec_id) = 0;

	// 获取/设置视频编码方式(软硬编)
	virtual VideoCodecMode getVideoEnCodecMode() = 0;
	virtual bool setVideoEnCodecMode(VideoCodecMode codec_mode) = 0;

	// 获取/设置视频解码方式(软硬解)
	virtual VideoCodecMode getVideoDeCodecMode() = 0;
	virtual bool setVideoDeCodecMode(VideoCodecMode codec_mode) = 0;

    // 获取/设置视频解码器是否用Generic copymode
    virtual bool isVideoDecoderGenericCopy() = 0;
    virtual void setVideoDecoderGenericCopy(bool enable) = 0;

	// 获取/设置视频编码最大码率
	virtual uint32_t getVideoMaxAvergeBitrate() = 0;
	virtual bool setVideoMaxAvergeBitrate(uint32_t bitrate) = 0;

    virtual int getAudioQuality() = 0;

    virtual void setAudioQuality(int quality) = 0;

    virtual int getAudioSampleRate() = 0;

    virtual void setAudioSampleRate(int sampleRate) = 0;

    virtual BOOL isSpeakerOn() = 0;

    virtual void setSpeaker(BOOL on) = 0;

    virtual void setMute(BOOL on) = 0;

    virtual void setSpeakerMute(BOOL on) = 0;

    virtual BOOL isMuted() = 0;

    virtual BOOL isSpeakerMuted() = 0;

    virtual void setCameraOn(BOOL on) = 0;

    virtual BOOL isCameraOn() = 0;

    virtual void setDenoiseLevel(int level) = 0;

    virtual int getDenoiseLevel() = 0;

    virtual int getMaxAudioMixingNumber() = 0;

    virtual void setMaxAudioMixingNumber(int maxMixing) = 0;

    virtual std::shared_ptr<NVExternalAudioStreamProtocol> addExternalAudioStream(int inSampleRate, int inChannelCnt) = 0;

    virtual void removeExternalAudioStream(int streamIdx) = 0;

//- (void) setCallkitEnabled:(BOOL)enabled;
//- (void) setCallkitBannedCountries:(NSArray *)bannedCountries;
//- (BOOL) callkitEnabled;
    // 忽略callkit相关定义函数
//    BOOL isCallkitActive();
//
//    void setCallkitIcon(shared_const_buffer icon);
//
//    void setCallkitRingtone: (nullable
//    NSString *)
//
//    ringtone();
//
//    void updateCallkitCallerName: (nullable
//    NSString *)

//    name();
//
//    void updateLocalizedString();
//
//设置音频偏好模式，1.低延迟模式。2.高音质模式
    virtual void setAudioPreferredMode(YCKCallAudioPreferredMode preferredMode) = 0;

//设置视频偏好模式，1.流畅模式。2.清晰度模式
    virtual void setVideoPreferredMode(YCKCallVideoPreferredMode preferredMode) = 0;

/**
 *  添加通话委托
 *
 *  @param delegate 通话委托
 */
    virtual void addDelegate(std::shared_ptr<YCKCallManagerDelegate> delegate) = 0;

/**
 *  移除通话委托
 *
 *  @param delegate 通话委托
 */
    virtual void removeDelegate(std::shared_ptr<YCKCallManagerDelegate> delegate) = 0;

    /**
     * add whiteboard
     */
    virtual void registerWhiteboard(std::shared_ptr<YCKAbstractWhiteboard> wb,int wid) =0;

    /**
     * remove whiteboard
     */
    virtual void unRegisterWhiteboard(std::shared_ptr<YCKAbstractWhiteboard> wb,int wid)=0;

    virtual void setP2pEnabledRatio(int maxRatio)=0; //0表示不用p2p，100表示最大p2p流量
    virtual int p2pEnabledRatio() const=0;

    /**
     * Release signal channel and other resources hold by callmanager.
     * When callmanager closed, it cannot receive calls or call out anymore.
     * Only call it before destruction.
     */
    virtual void close() = 0;

    virtual const NVDefAudioFilterConfig getDefaultAudioFilterConfig() const =0;
    virtual void setDefaultAudioFilterConfig(const NVDefAudioFilterConfig& cfg) =0;

    ///设置需要混音的成员集合，成员为int64形式的uid，list为null时无控制，所有成员的音频都接受。非nil时，只有集合中的uid的成员的音频会被混音播放。
    ///用于分组讨论情况下，可以控制一个人听哪些人的音频。如果要控制一个人仅对部分人说话，那么需要发信令让所有的人自己设置这个list来决定是否听。
    virtual void setAudioAcceptList(const int64_t* const uidList, size_t listsize) = 0;

    /**
    * 设置虚拟背景方法.
    */
    virtual bool SetVirtualBackgroundAlgorithm(VirtualBackgroundAlgorithm algorithm) = 0;
    /**
    * 获取虚拟背景方法.
    */
    virtual VirtualBackgroundAlgorithm GetVirtualBackgroundAlgorithm() = 0;
    /**
    * 设置虚拟背景背景图像文件.
    */
    virtual bool SetVirtualBackgroundBackground(const std::string& image) = 0;
    /**
    * 获取虚拟背景背景图像文件.
    */
    virtual std::string GetVirtualBackgroundBackground() = 0;
	/**
	* 重置虚拟背景背景图像文件.
	*/
	virtual void ResetVirtualBackgroundBackground() = 0;

    virtual std::shared_ptr<const YCKNetworkInfo> networkInfo(int64_t uid) const = 0;

    //获取摄像头方向(旋转角度).需要摄像头已初始化过. 
    virtual YCKVideoOrientation getCameraOrientation() const = 0;
    //强制设置摄像头方向（旋转角度).如果自动获得了真实摄像头角度，这个会覆盖它.需要摄像头已初始化过. 
    virtual void forceSetCameraOrientation(YCKVideoOrientation o) = 0;
};

#endif /* YCKCallManagerProtocol_h */
