//
//  PBX.m
//  rainbow
//
//  Created by Doha Tubaileh on 9/15/19.
//  Copyright © 2019 Facebook. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "CurrentCall.h"
#import <React/RCTLog.h>
#import <WebRTC/WebRTC.h>
#import "Rainbow/Rainbow.h"
#import "IEventEmmiter.h"
#import "Contact+DictRepresentation.h"
#import "PBXEventsNames.h"
#import "Call+DictRepresentation.h"
#import "Navigation.h"
#import "RTCCall+DictRepresentation.h"
#import <React/RCTRootView.h>

@interface CurrentCall ()
@property (strong, nonatomic) RTCCall *currentCall;
@property (strong, nonatomic) RTCService *rtcService;
@property (strong, nonatomic) TelephonyService *telephonyService;
@property (strong, nonatomic) ConferencesManagerService *conferencesManagerService;
@property (strong, nonatomic) IEventEmmiter *eventEmitter;
@property (nonatomic, weak) RCTBridge *bridge;
@property (nonatomic, weak) CallsManager *callsManager;

@property (nonatomic) BOOL isMicMuted;

@end

@implementation CurrentCall

RCT_EXPORT_MODULE();

- (instancetype)init {
    self = [super init];
    if (self) {
        _rtcService = [ServicesManager sharedInstance].rtcService;
        _callsManager = [ServicesManager sharedInstance].callsManager;
        _telephonyService = [ServicesManager sharedInstance].telephonyService;
        _conferencesManagerService = [ServicesManager sharedInstance].conferencesManagerService;
        _isMicMuted = NO;
        [self registerWebrtcEvents];
    }
    return self;
}

- (void)dealloc {
    [self unRegisterWebrtcEvents];
}

+ (BOOL)requiresMainQueueSetup
{
    return NO;
}

RCT_EXPORT_METHOD(retrieveCurrentCall) {
    NSLog(@"[CurrentCall] retrieveCurrentCall called");
    [[Navigation sharedManager] moveViewToCall];
}

RCT_EXPORT_METHOD(getCurrentCall) {
    NSLog(@"[CurrentCall] getCurrentCall called");
    NSDictionary *callDic;
    if (_rtcService.calls > 0 && _rtcService.hasSomeCalls) {
        RTCCall *currentCall = _rtcService.calls[0];
        if ([currentCall.peer class] == [Room class]) {//Conference Call
            callDic = [currentCall conferenceCallToDictionaryRepresentation];
        }
        else {//P2P
            callDic = [currentCall rtcCallToDictionaryRepresentation];
        }
    }
    else {// PBX
        Call *activeCall = [_telephonyService currentActiveCall];
        callDic = activeCall == nil ? nil : [activeCall pBxCallToDictionaryRepresentation];
    }
    
    [self sendEventWithName:@"current_call" eventBody:callDic];
}

RCT_EXPORT_METHOD(switchMicState) {
    NSLog(@"[CurrentCall] switchMicState called");
    _currentCall =  _rtcService.calls.firstObject;    

    BOOL isMute = 0 ;
    // Conference Call
    if ([_currentCall.peer class] == [Room class]) {
        Room *calledRoom = (Room*)[_currentCall peer];
        Conference *roomConference = calledRoom.conference;
        ConferenceParticipant *myParticipant = roomConference.getMyParticipant;
        isMute = myParticipant.muted;
        if (isMute) {
            [_conferencesManagerService changeMuteParticipantState:calledRoom conferenceParticipant:myParticipant muted:NO completionHandler:^(NSError * _Nullable error, BOOL askToUnmuteSuccess) {
                NSLog(@"[CurrentCall] switchMicState participant has muted ? %d", askToUnmuteSuccess);

            }];
        }
        else {
            [_conferencesManagerService changeMuteParticipantState:calledRoom conferenceParticipant:myParticipant muted:YES completionHandler:^(NSError * _Nullable error, BOOL askToUnmuteSuccess) {
                NSLog(@"[CurrentCall] switchMicState participant has unMuted ? %d", askToUnmuteSuccess);

            }];
        }
        [self sendEventWithName:@"mic_state_updated" eventBody:[NSNumber numberWithBool: !isMute]];

    }
    else {
        // P2P Call
        if (_isMicMuted) {
            NSLog(@"[CurrentCall] switchMicState should unmute");
            [_callsManager setMutedState:NO forCall:_currentCall completionBlock:^(NSError * _Nullable error) {
                NSLog(@"[CurrentCall] switchMicState unmute failed %@", error);

            }];
        }
        else {
            NSLog(@"[CurrentCall] switchMicState: mute");
            [_callsManager setMutedState:YES forCall:_currentCall completionBlock:^(NSError * _Nullable error) {
                NSLog(@"[CurrentCall] switchMicState mute failed %@", error);
            }];
        }
        // sending event to react will be handeled in didSwitchMicState
    }
}

RCT_EXPORT_METHOD(finishCallActivity) {
    NSLog(@"[CurrentCall] finishCallActivity called");
    [[Navigation sharedManager] moveViewToRainbow];
}

RCT_EXPORT_METHOD(getMicState) {
    BOOL isMute ;
    // Conference Call
    if ([_currentCall.peer class] == [Room class]) {
        Room *calledRoom = (Room*)[_currentCall peer];
        Conference *roomConference = calledRoom.conference;
        ConferenceParticipant *myParticipant = roomConference.getMyParticipant;
        isMute = myParticipant.muted;
    }
    else {
        // P2P Call
        isMute = _isMicMuted;
    }
        NSLog(@"[CurrentCall] send event for getMicState %d",isMute);
        [self sendEventWithName:@"mic_state_updated" eventBody:[NSNumber numberWithBool: isMute]];
}

RCT_EXPORT_METHOD(getSpeakerState) {
    NSLog(@"[CurrentCall] getSpeakerState called");
    [self sendEventWithName:@"speaker_state_updated" eventBody:[NSNumber numberWithBool:[_callsManager isSpeakerEnabled]]];
}

RCT_EXPORT_METHOD(switchSpeakerState) {
    NSLog(@"[CurrentCall] switchSpeakerState called");
    if ([_callsManager isSpeakerEnabled] == YES) {
        [_rtcService unForceAudioOnSpeaker];
    }
    else {
        [_rtcService forceAudioOnSpeaker];
    }
}

RCT_EXPORT_METHOD(sendDTMF:(NSString*)digit) {
    NSLog(@"[CurrentCall] sendDTMF with digit : %@",digit);
    [_rtcService sendDTMF:digit];
}

#pragma mark - Literner for Speaker Changes

-(void)handleRouteChange:(NSNotification *) notification {
    NSLog(@"[CurrentCall]handleRouteChange, is speaker enabled: %d",[_callsManager isSpeakerEnabled]);
    [self sendEventWithName:@"speaker_state_updated" eventBody:[NSNumber numberWithBool:[_callsManager isSpeakerEnabled]]];
}

#pragma mark - Listener for the Call Container Loaded on React side

-(void) didFinishLoadingCallContainer:(NSNotification *) notification {
    NSLog(@"[CurrentCall] didFinishLoadingCallContainer");
    RCTRootView *currentView = (RCTRootView*)notification.object;
        // This Event trigger when the `call_activity` is finished loading from the React side.
        [self getCurrentCall];
}

-(void)didSwitchMicState:(NSNotification *) notification{
    BOOL isMicMuted = [_callsManager isMicrophoneMuted];
    NSLog(@"[CurrentCall] didSwitchMicState, is muted enabled: %@", isMicMuted ? @"YES" : @"NO");
    _isMicMuted = isMicMuted;
    [self sendEventWithName:@"mic_state_updated" eventBody:@(isMicMuted)];

}
- ( IEventEmmiter *)eventEmitter {
    if (!_eventEmitter) {
        _eventEmitter = [self.bridge moduleForClass:[IEventEmmiter class]];
    }
    return _eventEmitter;
}
-(void)registerWebrtcEvents {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRouteChange:) name:AVAudioSessionRouteChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishLoadingCallContainer:) name:RCTContentDidAppearNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didSwitchMicState:) name:kRTCServiceDidMuteUnmuteCall object:nil];

}
-(void)unRegisterWebrtcEvents {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTContentDidAppearNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionRouteChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didSwitchMicState:) name:kRTCServiceDidMuteUnmuteCall object:nil];

}
- (void)sendEventWithName:(NSString *)eventName eventBody:(id)eventBody {
    IEventEmmiter *eventEmitter = [self eventEmitter];
    if (eventEmitter) {
        NSLog(@" [CurrentCall] sendEventWithName: %@ ", eventName);
        [eventEmitter sendEvent:eventName eventBody:eventBody];
    } else {
        NSLog(@"[CurrentCall] sendEventWithName:  Bridge is not ready. Cannot send event: %@", eventName);
    }
}

@end
