/*
 * Copyright (C) 2021-2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TELEPHONY_AUDIO_MANAGER_H
#define TELEPHONY_AUDIO_MANAGER_H

#include <set>

#include "audio_device_manager.h"
#include "audio_scene_processor.h"
#include "call_state_listener_base.h"
#include "ffrt.h"
#include "ring.h"
#include "singleton.h"
#include "sound.h"
#include "tone.h"

namespace OHOS {
namespace Telephony {
class AudioControlManager : public CallStateListenerBase, public std::enable_shared_from_this<AudioControlManager> {
    DECLARE_DELAYED_SINGLETON(AudioControlManager)

public:
    void Init();
    void UnInit();
    int32_t SetAudioDevice(const AudioDevice &device);
    int32_t SetAudioDevice(const AudioDevice &device, bool isByUser);
    bool PlayRingtone(); // plays the default ringtone
    bool StopRingtone();
    int32_t PlayRingback();
    int32_t StopRingback();
    int32_t PlayWaitingTone();
    int32_t StopWaitingTone();
    int32_t PlayDtmfTone(char str);
    int32_t StopDtmfTone();
    int32_t OnPostDialNextChar(char str);
    int32_t PlayCallTone(ToneDescriptor type);
    int32_t StopCallTone();
    int32_t MuteRinger();
    int32_t SetMute(bool on);
    void SetVolumeAudible();
    bool IsTonePlaying();
    bool IsAudioActivated() const;
    bool IsCurrentRinging() const;
    bool IsActiveCallExists() const;
    bool ShouldSwitchActive() const;
    bool ShouldSwitchDialing() const;
    bool ShouldSwitchAlerting() const;
    bool ShouldSwitchIncoming() const;
    AudioDeviceType GetInitAudioDeviceType(const sptr<CallBase> &callObjectPtr = nullptr) const;
    std::set<sptr<CallBase>> GetCallList();
    sptr<CallBase> GetCurrentActiveCall();
    AudioInterruptState GetAudioInterruptState();
    bool UpdateCurrentCallState();
    void SetRingState(RingState state);
    void SetSoundState(SoundState state);
    void SetToneState(ToneState state);
    void SetLocalRingbackNeeded(bool isNeeded);
    void NewCallCreated(sptr<CallBase> &callObjectPtr) override;
    void CallDestroyed(const DisconnectedDetails &details) override;
    void IncomingCallActivated(sptr<CallBase> &callObjectPtr) override;
    void IncomingCallHungUp(sptr<CallBase> &callObjectPtr, bool isSendSms, std::string content) override;
    void CallStateUpdated(sptr<CallBase> &callObjectPtr, TelCallState priorState, TelCallState nextState) override;
    void VideoStateUpdated(
        sptr<CallBase> &callObjectPtr, VideoStateType priorVideoState, VideoStateType nextVideoState);
    void CheckTypeAndSetAudioDevice(sptr<CallBase> &callObjectPtr, VideoStateType priorVideoState,
        VideoStateType nextVideoState, AudioDeviceType &initDeviceType, AudioDevice &device);
    void UpdateDeviceType(const sptr<CallBase> &callObjectPtr = nullptr);
    void UpdateDeviceTypeForCrs(AudioDeviceType deviceType);
    void UpdateDeviceTypeForVideoDialing();
    void MuteNetWorkRingTone(bool isMute = true);
    bool IsVideoCall(VideoStateType videoState);
    void StopVibrator();
    bool IsSoundPlaying();
    bool StopSoundtone();
    bool PlaySoundtone();
    void PlayCallEndedTone();
    void HandleNotNormalRingerMode();
    bool IsDistributeCallSinkStatus();
    void SetRingToneVolume(float volume);
    bool IsScoTemporarilyDisabled();
    void ExcludeBluetoothSco();
    void UnexcludeBluetoothSco();
    bool PlayForNoRing();
    bool StopForNoRing();
    bool NeedPlayVideoRing(ContactInfo &contactInfo, sptr<CallBase> &callObjectPtr);
    bool IsSystemVideoRing(sptr<CallBase> &callObjectPtr);
#ifdef CALL_MANAGER_SOS_NO_RINGBACK_TONE
    bool IsSosNoRingbackToneEnable();
#endif
    bool ShouldPlaySoundTone();
    bool ShouldPlayRingback();
    void SetCallAudioMode(int32_t mode, int32_t scenarios);
    static void SetIncomingConflict(bool isConflict);

private:
    RingState ringState_ = RingState::STOPPED;
    void HandleNextState(sptr<CallBase> &callObjectPtr, TelCallState nextState);
    void ApplyFocusForBlueToothCall(TelCallState nextState);
    void HandlePriorState(sptr<CallBase> &callObjectPtr, TelCallState priorState);
    void HandleCallStateUpdatedForVoip(sptr<CallBase> &callObjectPtr, TelCallState priorState, TelCallState nextState);
    bool PreHandleAnswerdState(sptr<CallBase> &callObjectPtr, TelCallState priorState, TelCallState nextState);
    void HandleCallStateUpdated(sptr<CallBase> &callObjectPtr, TelCallState priorState, TelCallState nextState);
    void HandleNewActiveCall(sptr<CallBase> &callObjectPtr);
    bool IsNumberAllowed(const std::string &phoneNum);
    sptr<CallBase> GetCallBase(int32_t callId);
    AudioInterruptState audioInterruptState_ = AudioInterruptState::INTERRUPT_STATE_DEACTIVATED;
    bool ShouldPlayRingtone() const;
    bool DealCrsScene(const AudioStandard::AudioRingerMode &ringMode, int32_t accountId);
    bool IsEmergencyCallExists();
    void UpdateForegroundLiveCall();
    void ProcessAudioWhenCallActive(sptr<CallBase> &callObjectPtr);
    void ResumeCrsSoundTone();
    int32_t HandleDistributeAudioDevice(const AudioDevice &device);
    int32_t HandleWirelessAudioDevice(const AudioDevice &device);
    void GetWirelessAudioDeviceAddress(AudioDeviceType deviceType, std::string &address);
    void SendMuteRingEvent();
    bool IsRingingVibrateModeOn();
    bool IsVoIPCallActived();
    int32_t SwitchAudioDevice(AudioDeviceType audioDeviceType, bool isSetAudioDeviceByUser);
    bool IsBtCallDisconnected();
    void AdjustVolumesForCrs();
    void SaveVoiceVolume(int32_t volume);
    int32_t GetBackupVoiceVolume();
    void RestoreVoiceValumeIfNecessary();
    void PostProcessRingtone();
    bool IsExternalAudioDevice(AudioDeviceType initDeviceType);
    bool IsInEarAudioDevice(AudioDeviceType initDeviceType);
    void UpdateDeviceForForegroundCall(const sptr<CallBase> &foregroundCall);
    void AdjustDeviceForCrs(AudioDevice &device, AudioDeviceType deviceType);
    void UnmuteSoundTone();
    void ProcessSoundtone(sptr<CallBase> &callObjectPtr);
    void MuteWaitingTone();
    void PlayRingtone(const sptr<CallBase>& incomingCall,
        const CallAttributeInfo& info, const ContactInfo& contactInfo);
    void PlayRing(const sptr<CallBase>& incomingCall, const CallAttributeInfo& info, const ContactInfo& contactInfo);
    AudioDeviceType GetInitAudioDeviceTypeOfRemote() const;

    ToneState toneState_ = ToneState::STOPPED;
    SoundState soundState_ = SoundState::STOPPED;
    bool isLocalRingbackNeeded_ = false;
    bool isCrsVibrating_ = false;
    bool isCrsStartSoundTone_ = false;
    bool isVideoRingVibrating_ = false;
    std::set<sptr<CallBase>> totalCalls_;
    std::shared_ptr<Ring> ring_{nullptr};
    std::unique_ptr<Tone> tone_;
    std::unique_ptr<Sound> sound_;
    ffrt::mutex mutex_;
    std::recursive_mutex toneStateLock_;
    sptr<CallBase> frontCall_ = nullptr;
    bool isSetAudioDeviceByUser_ = false;
    bool isScoTemporarilyDisabled_ = false;
    int32_t voiceVolume_ = -1;
    AudioDeviceType initCrsDeviceType_ = AudioDeviceType::DEVICE_UNKNOWN;
    ffrt::mutex crsMutex_{};
    std::unique_ptr<AudioStandard::AudioRenderer> audioRenderer_ = nullptr;
    ffrt::mutex audioRendererMutex_{};
    ffrt::recursive_mutex ringMutex_{};
    bool isPlayForNoRing_ = false;
    static bool isIncomingConflict_;
    static ffrt::mutex incomingMutex_;
};
} // namespace Telephony
} // namespace OHOS
#endif // TELEPHONY_AUDIO_MANAGER_H