// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "Voice/CsdkVoiceBase.h"
#if PLATFORM_ANDROID
#include "Platform/Android/AndroidGateway.h"
#endif
#include "../Voice/Data/CsdkUserMicStatus.h"
#include "CsdkVoiceSupportSubsystem.generated.h"


DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCsdkOnStopPlayVoice);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnUserEnterVoiceRoom,const TArray<FString>&, OpenIds);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnUserExitVoiceRoom,const TArray<FString>&, OpenIds);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnVoiceRoomDisconnect,int32, Result,const FString&, ErrorInfo);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnVoiceRoomReconnectStart,int32, Result,const FString&, ErrorInfo);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnVoiceRoomReconnectSuccess,int32, Result,const FString&, ErrorInfo);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMicStatusChanged,bool,bIsOpen);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMembersSpeakStart ,const TArray<FString>&, OpenIds);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMembersSpeakStop ,const TArray<FString>&, OpenIds);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMembersMicOpened ,const TArray<FString>&, OpenIds);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMembersMicClosed ,const TArray<FString>&, OpenIds);

DECLARE_DYNAMIC_DELEGATE_TwoParams(FModifyUserMicStatusCallback , int32, Result,const FString&, ErrMsg);
/**
 * 
 */
UCLASS()
class CSDKRUNTIME_API UCsdkVoiceSupportSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
public:
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;
	virtual void Deinitialize() override;

	/**
	 * @brief 初始化语音
	 * @param VoiceObj GME或者Gvoice的UObject包装对象
	 * @return 初始化结果
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	bool Init(UCsdkVoiceBase* VoiceObj);

	/**
	 * @brief 反初始化语音
	 * @return 反初始化结果
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 Uninit();

	/**
	 * @brief 暂停语音功能
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 Pause() ;

	/**
	 * @brief 恢复语音功能
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 Resume() ;
	
	/**
	 * @brief 开始录制语音
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 StartRecording(const FRecordFileCompleted& OnRecordFileCompleted) ;

	/**
	 * @brief 停止录制语音
	 * @param OnRecordFileCompleted 停止录制语音文件回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 StopRecording() ;

	/** 
	 * @brief 取消录制语音
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 CancelRecording();

	/**
	 * @brief 上传语音文件
	 * @param FilePath 语音文件的路径，此路径为本地路径
	 * @param OnUploadRecordedFileCompleted 上传完成回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 UploadRecordedFile(const FString& FilePath, const FUploadRecordedFileCompleted& OnUploadRecordedFileCompleted) ;

	/**
	 * @brief 下载语音文件
	 * @param FileId 语音文件url
	 * @param OnDownloadRecordedFileCompleted 下载完成回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 DownloadRecordedFile(const FString& FileId, const FDownloadRecordedFileCompleted& OnDownloadRecordedFileCompleted);

	/**
	 * @brief 
	 * @param FilePath 	播放语音文件
	 * @param PlayRecordedFileCompleted 播放完成回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable,Category="CsdkVoice")
	int32 PlayRecordedFile(const FString& FilePath,const FPlayRecordedFileCompleted& PlayRecordedFileCompleted) ;

	/**
	 * @brief 停止播放语音文件
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 StopPlayFile() ;
	
	/**
	 * @brief 获取语音文件大小
	 * @param FilePath 语音文件的路径，此路径为本地路径
	 * @return 语音文件大小，单位为字节
	 */
	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	int32 GetFileSize(const FString& FilePath) const;
	
	/**
	 * @brief 获取语音文件时长
	 * @param FilePath 语音文件的路径，此路径为本地路径
	 * @return 语音文件时长，单位为秒
	 */
	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	float GetVoiceFileDuration(const FString& FilePath) const; 
	
	/**
	 * @brief 语音文件转文本
	 * @param FileId 语音文件url
	 * @param SpeechToTextCompleted 语音文件转文本回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 SpeechToText(const FString& FileId,const FSpeechToTextCompleted& SpeechToTextCompleted);

	/**
	 * @brief  开始流式语音转文本
	 * @param StreamSpeechToTextRunning 录制过程中实时返回的文本，GME有此回调，GVoice无此回调
	 * @param StreamSpeechToTextCompleted 录制完成后返回的文本信息
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 StartStreamSpeechToText(const FStreamSpeechToTextRunning& StreamSpeechToTextRunning,
		const FStreamSpeechToTextCompleted& StreamSpeechToTextCompleted);
	
	/**
	 * @brief 停止流式语音转文本
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 StopStreamSpeechToText();
	
	/**
	 * @brief 进入语音房间
	 * @param RoomId 房间号
	 * @param EnterRoomCompleted 进入语音房间完成回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 EnterVoiceRoom(const FString& RoomId, const FEnterRoomCompleted& EnterRoomCompleted);
	
	/**
	 * @brief 退出语音房间
	 * @param ExitRoomCompleted 退出语音房间完成回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 ExitVoiceRoom(const FExitRoomCompleted& ExitRoomCompleted);


	/**
	 * @brief 切换语音房间
	 * @param RoomId 新语音房间
	 * @param SwitchRoomCompleted 切换语音房间回调
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 SwitchVoiceRoom(const FString& RoomId, const FSwitchRoomCompleted& SwitchRoomCompleted);
	
	/**
	 * @brief 获取房间成员
	 * @return 成员列表
	 */
	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	TArray<FString> GetVoiceRoomMemberOpenIds() const;

	/**
	 * @brief 打开麦克风
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 OpenMic();
	
	/**
	 * @brief 关闭麦克风
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 CloseMic();
	
	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	ECsdkMicState GetMicState();
	/**
	 * @brief 打开扬声器
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 OpenSpeaker();
	
	/**
	 * @brief 关闭扬声器
	 * @return 语音SDK原生错误码
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 CloseSpeaker();
	
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	ECsdkSpeakerState GetSpeakerState();

	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	bool HasVoiceRoom();
	
	/**
	 * 修改用户麦克风状态
	 * @param VoiceRoomId 语音房间ID
	 * @param UserStatus 用户及控制状态
	 * @param Callback 请求是否成功的回调
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	void ModifyUserMicStatus(FString VoiceRoomId, TArray<FCsdkUserMicStatus> UserStatus, FModifyUserMicStatusCallback Callback);
	

	/**
	 * 设置麦克风音量的增益。
	 * @param Vol 音量增益大小，取值 [0，200]，其中 100 为默认值，相当于音量大小不增不减。
	 * @return 设置后的麦克风音量
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 SetMicVolume(int32 Vol);
	
	/**
	 * 获取麦克风软件音量
	 * @return 获取的是之前设置的值，默认返回100
	 */
	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	int32 GetMicVolume();
	
	

	/**
	 * 设置扬声器的音量
	 * @param Vol 音量增益大小，取值 [0，200]，其中 100 为默认值，相当于音量大小不增不减。
	 * @return 设置后的扬声器音量
	 */
	UFUNCTION(BlueprintCallable, Category="CsdkVoice")
	int32 SetSpeakerVolume(int32 Vol);
	

	/**
	 * 获取扬声器的音量
	 * @return 获取使用 SetSpeakerVolume 设置的扬声器音量增益大小
	 */
	UFUNCTION(BlueprintPure, Category="CsdkVoice")
	int32 GetSpeakerVolume();

	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnUserEnterVoiceRoom OnUserEnterVoiceRoom;
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnUserExitVoiceRoom OnUserExitVoiceRoom;
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnVoiceRoomDisconnect OnVoiceRoomDisconnect;
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnVoiceRoomReconnectStart OnVoiceRoomReconnectStart;
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnVoiceRoomReconnectSuccess OnVoiceRoomReconnectSuccess;
	
	/**
	 * 当前用户被修改的实时语音状态的通知
	 */
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnMicStatusChanged OnMicStatusChanged;
	
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnMembersSpeakStart OnMembersSpeakStart;
	
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnMembersSpeakStop OnMembersSpeakStop;
	
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnMembersMicOpened OnMembersMicOpened;
	
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FOnMembersMicClosed OnMembersMicClosed;
	
	UPROPERTY(BlueprintAssignable,Category="CsdkVoice")
	FCsdkOnStopPlayVoice CsdkOnStopPlayVoice;


#if PLATFORM_ANDROID
	TSharedPtr<FAndroidGateway> AndroidGateway;
#endif
	
private:
	UPROPERTY()
	TObjectPtr<UCsdkVoiceBase> Voice;
	bool bIsInit = false;

};
