/*
 * Copyright (C) 2023 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.
 */

#include "voip_call.h"

#include "call_control_manager.h"
#include "call_manager_errors.h"
#include "call_manager_hisysevent.h"
#include "call_object_manager.h"
#include "telephony_log_wrapper.h"
#include "voip_call_connection.h"

namespace OHOS {
namespace Telephony {
const int32_t AUDIO_EVENT_MUTED_RINGTONE = 4;
const int32_t AUDIO_EVENT_MUTE = 1;
VoIPCall::VoIPCall(DialParaInfo &info) : CarrierCall(info)
{
    callId_ = info.callId;
    voipCallId_ = info.voipCallInfo.voipCallId;
    userName_ = info.voipCallInfo.userName;
    userProfile_.assign((info.voipCallInfo.userProfile).begin(), (info.voipCallInfo.userProfile).end());
    abilityName_ = info.voipCallInfo.abilityName;
    extensionId_ = info.voipCallInfo.extensionId;
    voipBundleName_ = info.voipCallInfo.voipBundleName;
    showBannerForIncomingCall_ = info.voipCallInfo.showBannerForIncomingCall;
    isConferenceCall_ = info.voipCallInfo.isConferenceCall;
    isVoiceAnswerSupported_ = info.voipCallInfo.isVoiceAnswerSupported;
    isUserMuteRingToneAllowed_ = info.voipCallInfo.isUserMuteRingToneAllowed;
    isDialingAllowedDuringCarrierCall_ = info.voipCallInfo.isDialingAllowedDuringCarrierCall;
    hasMicPermission_ = info.voipCallInfo.hasMicPermission;
    isCapsuleSticky_ = info.voipCallInfo.isCapsuleSticky;
    uid_ = info.voipCallInfo.uid;
}

VoIPCall::~VoIPCall() {}

int32_t VoIPCall::DialingProcess()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::AnswerCall(int32_t videoState, bool isRTT)
{
    TELEPHONY_LOGI("VoIPCall::AnswerCall");
    VoipCallEventInfo voipcallInfo;
    int32_t ret = TELEPHONY_ERROR;
    ret = PackVoipCallInfo(voipcallInfo);
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGW("PackVoipCallInfo failed!");
    }
    DelayedSingleton<VoipCallConnection>::GetInstance()->AnswerCall(voipcallInfo, videoState);
    CallManagerHisysevent::RecordVoipProcedure(voipcallInfo.voipCallId,
        VoipProcedureEvent::CALLMANAGER_ANSWER_VOIP, static_cast<int32_t>(videoState));
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGE("answer call failed!");
        return CALL_ERR_ANSWER_FAILED;
    }
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::PackVoipCallInfo(VoipCallEventInfo &voipcallInfo)
{
    voipcallInfo.voipCallId = voipCallId_;
    voipcallInfo.bundleName = voipBundleName_;
    voipcallInfo.uid = uid_;
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::RejectCall()
{
    TELEPHONY_LOGI("VoIPCall::RejectCall enter");
    VoipCallEventInfo voipcallInfo;
    int32_t ret = TELEPHONY_ERROR;
    ret = PackVoipCallInfo(voipcallInfo);
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGW("PackVoipCallInfo failed!");
    }
    DelayedSingleton<VoipCallConnection>::GetInstance()->RejectCall(voipcallInfo);
    CallManagerHisysevent::RecordVoipProcedure(voipcallInfo.voipCallId,
        VoipProcedureEvent::CALLMANAGER_REJECT_VOIP, static_cast<int32_t>(ret));
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGE("reject call failed!");
        return CALL_ERR_ANSWER_FAILED;
    }
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::HangUpCall()
{
    TELEPHONY_LOGI("VoIPCall::HangUpCall enter");
    VoipCallEventInfo voipcallInfo;
    int32_t ret = TELEPHONY_ERROR;
    ret = PackVoipCallInfo(voipcallInfo);
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGW("PackVoipCallInfo failed!");
    }
    voipcallInfo.errorReason = ErrorReason::USER_ANSWER_CELLULAR_FIRST;
    DelayedSingleton<VoipCallConnection>::GetInstance()->HangUpCall(voipcallInfo);
    CallManagerHisysevent::RecordVoipProcedure(voipcallInfo.voipCallId,
        VoipProcedureEvent::CALLMANAGER_HUNGUP_VOIP, static_cast<int32_t>(voipcallInfo.errorReason));
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGE("hangup call failed!");
        return CALL_ERR_ANSWER_FAILED;
    }
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::HangUpCall(const ErrorReason &status)
{
    TELEPHONY_LOGI("VoIPCall::dial cellularcall HangUpvoipCall enter");
    VoipCallEventInfo voipcallInfo;
    int32_t ret = TELEPHONY_ERROR;
    ret = PackVoipCallInfo(voipcallInfo);
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGW("PackVoipCallInfo failed!");
    }
    voipcallInfo.errorReason = status;
    DelayedSingleton<VoipCallConnection>::GetInstance()->HangUpCall(voipcallInfo);
    CallManagerHisysevent::RecordVoipProcedure(voipcallInfo.voipCallId,
        VoipProcedureEvent::CALLMANAGER_HUNGUP_VOIP, static_cast<int32_t>(voipcallInfo.errorReason));
    if (ret != TELEPHONY_SUCCESS) {
        TELEPHONY_LOGE("hangup call failed!");
        return CALL_ERR_ANSWER_FAILED;
    }
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::HoldCall()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::UnHoldCall()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::SwitchCall()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::SetMute(int32_t mute, int32_t slotId)
{
    CallAttributeInfo info;
    GetCallAttributeInfo(info);
    std::string voipCallId = info.voipCallInfo.voipBundleName + ":" + std::to_string(info.voipCallInfo.uid) + ":" +
        info.voipCallInfo.voipCallId;
    CallAudioEvent callAudioEvent;
    switch (mute) {
        case AUDIO_EVENT_MUTED_RINGTONE:
            callAudioEvent = CallAudioEvent::AUDIO_EVENT_MUTED_RINGTONE;
            break;
        case AUDIO_EVENT_MUTE:
            callAudioEvent = CallAudioEvent::AUDIO_EVENT_MUTED;
            break;
        default:
            callAudioEvent = CallAudioEvent::AUDIO_EVENT_UNMUTED;
            break;
    }
    TELEPHONY_LOGI("VoIPCall::setMute voipCallId: %{public}s, callAudioEvent: %{public}d", voipCallId.c_str(),
        callAudioEvent);
    DelayedSingleton<VoipCallConnection>::GetInstance()->SendCallUiEvent(voipCallId, callAudioEvent);
    CallManagerHisysevent::RecordVoipProcedure(info.voipCallInfo.voipCallId,
        VoipProcedureEvent::CALLMANAGER_MUTE_VOIP, static_cast<int32_t>(callAudioEvent));
    return TELEPHONY_SUCCESS;
}

void VoIPCall::GetCallAttributeInfo(CallAttributeInfo &info)
{
    GetCallAttributeCarrierInfo(info);
    info.callId = callId_;
    info.voipCallInfo.voipCallId = voipCallId_;
    info.voipCallInfo.userName = userName_;
    (info.voipCallInfo.userProfile).assign(userProfile_.begin(), userProfile_.end());
    info.voipCallInfo.extensionId = extensionId_;
    info.voipCallInfo.abilityName = abilityName_;
    info.voipCallInfo.voipBundleName = voipBundleName_;
    info.voipCallInfo.showBannerForIncomingCall = showBannerForIncomingCall_;
    info.voipCallInfo.isConferenceCall = isConferenceCall_;
    info.voipCallInfo.isVoiceAnswerSupported = isVoiceAnswerSupported_;
    info.voipCallInfo.isUserMuteRingToneAllowed = isUserMuteRingToneAllowed_;
    info.voipCallInfo.isDialingAllowedDuringCarrierCall = isDialingAllowedDuringCarrierCall_;
    info.voipCallInfo.hasMicPermission = hasMicPermission_;
    info.voipCallInfo.isCapsuleSticky = isCapsuleSticky_;
    info.voipCallInfo.uid = uid_;
    return;
}

bool VoIPCall::UpdateCallAttributeInfo(const CallDetailInfo &info)
{
    bool isChanged = false;
    if (hasMicPermission_ != info.voipCallInfo.hasMicPermission) {
        hasMicPermission_ = info.voipCallInfo.hasMicPermission;
        isChanged = true;
    }
    if (userName_ != info.voipCallInfo.userName) {
        userName_ = info.voipCallInfo.userName;
        isChanged = true;
    }
    if (userProfile_ != info.voipCallInfo.userProfile) {
        userProfile_ = info.voipCallInfo.userProfile;
        isChanged = true;
    }
    if (isConferenceCall_ != info.voipCallInfo.isConferenceCall) {
        isConferenceCall_ = info.voipCallInfo.isConferenceCall;
        isChanged = true;
    }
    VideoStateType originalType = GetVideoStateType();
    if (originalType != info.callMode) {
        TELEPHONY_LOGI("change VideoStateType from %{public}d to %{public}d",
            static_cast<int32_t>(originalType), static_cast<int32_t>(info.callMode));
        SetVideoStateType(info.callMode);
        isChanged = true;
    }
    TELEPHONY_LOGI("UpdateCallAttributeInfo isChanged: %{public}d", isChanged);
    return isChanged;
}

int32_t VoIPCall::CombineConference()
{
    return TELEPHONY_SUCCESS;
}

void VoIPCall::HandleCombineConferenceFailEvent()
{
    return;
}

int32_t VoIPCall::SeparateConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::KickOutFromConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::CanCombineConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::CanSeparateConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::CanKickOutFromConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::GetMainCallId(int32_t &mainCallId)
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::GetSubCallIdList(std::vector<std::u16string> &callIdList)
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::GetCallIdListForConference(std::vector<std::u16string> &callIdList)
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::IsSupportConferenceable()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::LaunchConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::ExitConference()
{
    return TELEPHONY_SUCCESS;
}

int32_t VoIPCall::HoldConference()
{
    return TELEPHONY_SUCCESS;
}

std::string VoIPCall::GetVoipCallId()
{
    return voipCallId_;
}

std::string VoIPCall::GetVoipBundleName()
{
    return voipBundleName_;
}

bool VoIPCall::GetUserMuteRingToneAllowed()
{
    return false;
}

int32_t VoIPCall::GetVoipUid()
{
    return uid_;
}
} // namespace Telephony
} // namespace OHOS