//
// Copyright 2016 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation
import SignalServiceKit

#if targetEnvironment(simulator)

class SimulatorCallUIAdaptee: NSObject, CallUIAdaptee {
    var callService: CallService { AppEnvironment.shared.callService }

    required init(showNamesOnCallScreen: Bool, useSystemCallLog: Bool) {
    }

    // MARK: 

    func startOutgoingCall(call: SignalCall) {
        AssertIsOnMainThread()

        switch call.mode {
        case .individual:
            self.callService.individualCallService.handleOutgoingCall(call)
        case .groupThread(let groupThreadCall):
            switch groupThreadCall.groupCallRingState {
            case .shouldRing where groupThreadCall.ringRestrictions.isEmpty, .ringing:
                // Let CallService call recipientAcceptedCall when someone joins.
                break
            case .ringingEnded:
                owsFailDebug("ringing ended while we were starting the call")
                fallthrough
            case .doNotRing, .shouldRing:
                // Immediately consider ourselves connected.
                recipientAcceptedCall(call.mode)
            case .incomingRing, .incomingRingCancelled:
                owsFailDebug("should not happen for an outgoing call")
                // Recover by considering ourselves connected
                recipientAcceptedCall(call.mode)
            }
        case .callLink:
            recipientAcceptedCall(call.mode)
        }
    }

    func reportIncomingCall(_ call: SignalCall, completion: @escaping (Error?) -> Void) {
        AssertIsOnMainThread()
        completion(nil)
    }

    func answerCall(_ call: SignalCall) {
        AssertIsOnMainThread()

        guard call.localId == self.callService.callServiceState.currentCall?.localId else {
            owsFailDebug("localId does not match current call")
            return
        }

        switch call.mode {
        case .individual:
            self.callService.individualCallService.handleAcceptCall(call)
        case .groupThread(let groupThreadCall):
            // Explicitly unmute to request permissions.
            self.callService.updateIsLocalAudioMuted(isLocalAudioMuted: false)
            self.callService.joinGroupCallIfNecessary(call, groupCall: groupThreadCall)
        case .callLink:
            owsFail("Can't answer Call Link call")
        }

        // Enable audio for locally accepted calls after the session is configured.
        self.audioSession.isRTCAudioEnabled = true
    }

    func recipientAcceptedCall(_ call: CallMode) {
        AssertIsOnMainThread()

        // Enable audio for remotely accepted calls after the session is configured.
        self.audioSession.isRTCAudioEnabled = true
    }

    func localHangupCall(_ call: SignalCall) {
        AssertIsOnMainThread()
        // If both parties hang up at the same moment, call might already be nil.
        owsAssert(self.callService.callServiceState.currentCall == nil || call.localId == self.callService.callServiceState.currentCall?.localId)
        callService.handleLocalHangupCall(call)
    }

    func remoteDidHangupCall(_ call: SignalCall) {
    }

    func remoteBusy(_ call: SignalCall) {
    }

    func didAnswerElsewhere(call: SignalCall) {
    }

    func didDeclineElsewhere(call: SignalCall) {
    }

    func wasBusyElsewhere(call: SignalCall) {
    }

    func failCall(_ call: SignalCall, error: CallError) {
    }

    func setIsMuted(call: SignalCall, isMuted: Bool) {
        AssertIsOnMainThread()
        owsAssert(call.localId == self.callService.callServiceState.currentCall?.localId)
        self.callService.updateIsLocalAudioMuted(isLocalAudioMuted: isMuted)
    }

    func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
        AssertIsOnMainThread()
        owsAssert(call.localId == self.callService.callServiceState.currentCall?.localId)
        self.callService.updateIsLocalVideoMuted(isLocalVideoMuted: !hasLocalVideo)
    }
}

#endif
