//
//  Telephony.m
//  rainbow
//
//  Created by Doha Tubaileh on 1/20/20.
//  Copyright © 2020 Facebook. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTLog.h>
#import "Telephony.h"
#import "Rainbow/Rainbow.h"
#import "IEventEmmiter.h"
#import "PBXEventsNames.h"
#import "ReactCallForwardStatus.h"
#import "TelephonyStatus.h"

#define CALL_FORWARDING_ERROR @"CALL_FORWARDING_ERROR"

@interface Telephony ()
@property (nonatomic,strong) MyUser *myUser;
@property (strong, nonatomic) TelephonyService *telephonyService;
@property (strong, nonatomic) PhoneNumber *myUserWorkMobile;
@property (strong, nonatomic) PhoneNumber *myUserPersonalMobile;
@property (strong, nonatomic) PhoneNumber *myUserPersonalPhone;
@property (nonatomic, strong) IEventEmmiter *eventEmitter;
@property (nonatomic, weak) RCTBridge *bridge;
@end

@implementation Telephony

RCT_EXPORT_MODULE();

- (instancetype)init {
    self = [super init];
    if (self) {
        self->_myUser = [ServicesManager sharedInstance].myUser;
        self->_telephonyService = [ServicesManager sharedInstance].telephonyService;
        
        _myUserWorkMobile = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeWork withDeviceType:PhoneNumberDeviceTypeMobile];
        _myUserPersonalMobile = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeMobile];
        _myUserPersonalPhone = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeLandline];
        //Listen when call forward status changed
        [self registerForwaringEvent];
        
        //Listen to Nomadic status changed
        [self registerNomadicEvent];
    }
    return self;
}

- (void)dealloc {
    [self unRegisterNomadicEvent];
    [self unRegisterForwaringEvent];
}

RCT_EXPORT_METHOD(switchNomadic:(BOOL)isNomadicSwitchChecked _:(BOOL)isVoipSwitchChecked swichBtnName:(NSString*)buttonId) {//TODO
    PhoneNumber *nomadicPhoneNumber = [self getMyUserNomadicPhoneNumber] ;
    if (nomadicPhoneNumber == nil) {
        [self sendEventWithName:NoNomadicNumberEntered eventBody:nil];
        return;
    }
    if (isNomadicSwitchChecked) {
        [[ServicesManager sharedInstance].telephonyService nomadicLoginWithPhoneString:nomadicPhoneNumber.numberE164 withVoIP:isVoipSwitchChecked withCompletionBlock:^(NSError *error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (error) {
                    NSLog(@"[Telephony] switchNomadic nomadicLogin failed with error: %@",error);
                } else {
                    //TODO: make sure to update the UI
                }
            });
        }];
    }
    else {
        [[ServicesManager sharedInstance].telephonyService nomadicLogoutWithCompletionBlock:^(NSError *error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (error) {
                    NSLog(@"[Telephony] switchNomadic nomadicLogout failed with error: %@",error);
                } else {
                    //TODO: make sure to update the UI
                }
            });
        }];
    }
}


RCT_EXPORT_METHOD(getForwardStatus){
    NSLog(@"[Telephony] getForwardStatus");
    [self getCurrentForwardStatus];
}

RCT_EXPORT_METHOD(redirectCallsToVoiceMail){
    __weak typeof(self) weakSelf = self;

    NSLog(@"[Telephony] redirectCallsToVoiceMail");
    [_telephonyService setForwardToVoicemailWithCompletionBlock:^(NSError * _Nullable error) {
        __strong typeof(weakSelf) strongSelf = weakSelf; // Create a strong reference to weakSelf within the block

        if (!strongSelf) {
            return; // Return early if strongSelf is nil
        }
        if (error) {
            NSLog(@"[Telephony]redirectCallsToVoiceMail: error %@",error);
            [strongSelf sendEventWithName:CallForwardingResult eventBody:CALL_FORWARDING_ERROR];
            return;
        }
        NSLog(@"[Telephony]redirectCallsToVoiceMail: success");
    }];
    
}

RCT_EXPORT_METHOD(cancelCallForward){
    NSLog(@"[Telephony] cancelCallForward");
    [_telephonyService cancelForwardWithCompletionBlock:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"[Telephony]cancelCallForward: error %@",error);
            [self sendEventWithName:CallForwardingResult eventBody:CALL_FORWARDING_ERROR];
            return;
        }
        NSLog(@"[Telephony]cancelCallForward: success");
        
    }];
}

RCT_EXPORT_METHOD(forwardCallsToPhoneNumber:(NSString*)number){
    NSLog(@"[Telephony] forwardCallsToPhoneNumber");
    __weak typeof(self) weakSelf = self;

    if (number == nil || !number.length) {
        NSLog(@"[Telephony] forwardCallsToPhoneNumber error this number is nil OR empty");
        return;
    }
    
    [_telephonyService setForwardToExternalPhoneString:number withCompletionBlock:^(NSError * _Nullable error) {
        __strong typeof(weakSelf) strongSelf = weakSelf; // Create a strong reference to weakSelf within the block

        if (!strongSelf) {
            return; // Return early if strongSelf is nil
        }
        if (error) {
            NSLog(@"[Telephony]forwardCallsToPhoneNumber: error %@",error);
            [strongSelf sendEventWithName:CallForwardingResult eventBody:CALL_FORWARDING_ERROR];
            return;
        }
        NSLog(@"[Telephony]forwardCallsToPhoneNumber: success");
    }];
    
}

RCT_EXPORT_METHOD(forwardToPersonalMobile){
    NSLog(@"[Telephony] forwardCallsToPhoneNumber");

    __weak typeof(self) weakSelf = self; // Create a weak reference to self

    [_telephonyService setForwardToExternalPhoneNumber:_myUserPersonalMobile withCompletionBlock:^(NSError * _Nullable error) {
        __strong typeof(weakSelf) strongSelf = weakSelf; // Create a strong reference to weakSelf within the block

        if (!strongSelf) {
            return; // Return early if strongSelf is nil
        }

        if (error) {
            NSLog(@"[Telephony]forwardCallsToPhoneNumber: error %@",error);
            [strongSelf sendEventWithName:CallForwardingResult eventBody:CALL_FORWARDING_ERROR];
            return;
        }
        NSLog(@"[Telephony]forwardCallsToPhoneNumber: success");
    }];
}

RCT_EXPORT_METHOD(forwardToPersonalPhone){
    NSLog(@"[Telephony] forwardCallsToPhoneNumber");
    __weak typeof(self) weakSelf = self; // Create a weak reference to self

    [_telephonyService setForwardToExternalPhoneNumber:_myUserPersonalPhone withCompletionBlock:^(NSError * _Nullable error) {
        __strong typeof(weakSelf) strongSelf = weakSelf; // Create a strong reference to weakSelf within the block

        if (!strongSelf) {
            return; // Return early if strongSelf is nil
        }
        if (error) {
            NSLog(@"[Telephony]forwardCallsToPhoneNumber: error %@",error);
            [strongSelf sendEventWithName:CallForwardingResult eventBody:CALL_FORWARDING_ERROR];
            return;
        }
        NSLog(@"[Telephony]forwardCallsToPhoneNumber: success");
    }];
    
}

RCT_EXPORT_METHOD(checkTelephonyCapabilities) {
    
    BOOL telephonySettingsEnabled = _myUser.isAllowedToUseTelephony && (_myUser.isAllowedToUseTelephonyNomadicMode || _myUser.isAllowedToUseTelephonyCallForward);
    PhoneNumber *nomadicNumber = [self getMyUserNomadicPhoneNumber];
    NSMutableDictionary *telephonyInfoDic = [[NSMutableDictionary alloc] init];
    
    
    BOOL isNomadicEnable = NO;
    BOOL isVOIPEnable = NO;
    BOOL isNomadicFeatureActivated = _myUser.isAllowedToUseTelephonyNomadicMode && _myUser.nomadicStatus.featureActivated;
    
    if (_myUser.isNomadicModeActivated) {//check nomadic number destination
        isNomadicEnable = YES;
    }
    
    if (_myUser.isAllowedToUseTelephonyWebRTCtoPSTN) {
        // TODO: handle those changes when upgrading from V 2.2.0 to 2.3.0
//        if (_myUser.isNomadicModeActivated && _myUser.mediaPillarStatus.activated && _myUser.mediaPillarStatus.featureActivated) {
//            isNomadicEnable = YES;
//            isVOIPEnable = _myUser.mediaPillarStatus.activated;
//        }
    }
    
    
    [telephonyInfoDic setValue:[NSNumber numberWithBool:telephonySettingsEnabled] forKey:@"isTelephonyEnabled"];
    [telephonyInfoDic setValue:nomadicNumber.numberE164 forKey:@"deviceNumber"];//????why do we need this
    //The value for the user nomadic value
    [telephonyInfoDic setValue:[NSNumber numberWithBool:isNomadicEnable] forKey:@"isNomadicEnabled"];
    //check if the user have nomadic feature to show him the nomadic view
    [telephonyInfoDic setValue:[NSNumber numberWithBool:isNomadicFeatureActivated] forKey:@"isNomadicFeatureActivated"];//if the user have nomadi
    [telephonyInfoDic setValue:[NSNumber numberWithBool:isVOIPEnable] forKey:@"isVoipEnabled"];//_myUser.mediaPillarStatus.activated
    
    NSLog(@"[Telephony] checkTelephonyCapabilities: %@",telephonyInfoDic);
    [self sendEventWithName:TelephonyCapabilityUpdate eventBody:telephonyInfoDic];
}


RCT_EXPORT_METHOD(unregisterNomadicStatusChangeListener){
    NSLog(@"[Telephony]unregisterNomadicStatusChangeListener");
    //  [self unRegisterNomadicEvent];
    //TODO: IOS is no need for this
}

RCT_EXPORT_METHOD(unregisterForwardStatusChangeListener){
    NSLog(@"[Telephony]unregisterForwardStatusChangeListener");
    //  [self unRegisterForwaringEvent];
    //TODO: IOS is no need for this
}

RCT_EXPORT_METHOD(getForwardOptions){
    NSLog(@"[Telephony]getForwardOptions");
    [self getForwardAvailableOptions];
}

RCT_EXPORT_METHOD(getNomadicNumber){
    NSLog(@"[Telephony]getNomadicNumber");
    NSString *nomadicNumber = [self getMyUserNomadicPhoneNumber].numberE164;
    
    [self sendEventWithName:NomadicNumberUpdated eventBody:nomadicNumber];
    
}

RCT_EXPORT_METHOD(getTelephonyStatus){
    NSLog(@"[Telephony]getTelephonyStatus");
    [self getCurrentTelephonyStatus];
}

RCT_EXPORT_METHOD(setNomadicNumber:(NSString*)number){
    NSLog(@"[Telephony]setNomadicNumber with number: %@",number);
    if (number == nil || number.length == 0) {
        return;
    }
    PhoneNumber *personalPhone =  [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeLandline];
    PhoneNumber *personalMobile =  [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeMobile];
    
    NSDictionary *fields = @{
        @"professional_mobilephone":number,
        @"professional_landphone":@"",
        @"personal_landphone":personalPhone.numberE164?personalPhone.numberE164:@"",
        @"personal_mobilephone":personalMobile.numberE164?personalMobile.numberE164:@""
    };
    [[ServicesManager sharedInstance].contactsManagerService updateUserWithFields:fields withCompletionBlock:^(NSError *error) {
        if (error) {
            NSLog(@"[Telephony]setNomadicNumber error: %@",error);
            
        }
        else {
            [self getNomadicNumber];
        }
    }];
    
}

#pragma mark - Notification Listeners

-(void) myUserCallForwardDidUpdate:(NSNotification *)notification {
    NSLog(@"[Telephony] myUserCallForwardDidUpdate");
    //Send the updated prop for the user
    _myUserWorkMobile = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeWork withDeviceType:PhoneNumberDeviceTypeMobile];
    _myUserPersonalMobile = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeMobile];
    _myUserPersonalPhone = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeLandline];
    [self getCurrentTelephonyStatus];
    [self checkTelephonyCapabilities];
    [self getForwardOptions];
    [self getCurrentForwardStatus];
}

-(void) myUserNomadicStatusDidUpdate:(NSNotification *)notification {
    NSLog(@"[Telephony] myUserNomadicStatusDidUpdate");
    //TODO: getNomadicNumber
    _myUserWorkMobile = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeWork withDeviceType:PhoneNumberDeviceTypeMobile];
    _myUserPersonalMobile = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeMobile];
    _myUserPersonalPhone = [_myUser.contact getPhoneNumberOfType:PhoneNumberTypeHome withDeviceType:PhoneNumberDeviceTypeLandline];
    [self getCurrentTelephonyStatus];
    [self checkTelephonyCapabilities];
    [self getNomadicNumber];
}

#pragma mark - Telephony Methodes

-(PhoneNumber *) getMyUserNomadicPhoneNumber {
    NSLog(@"[Telephony] getMyUserDeviceNumber");
    
    if (_myUserWorkMobile) {
        return _myUserWorkMobile;
    }
    else if (_myUserPersonalMobile) {
        return _myUserPersonalMobile;
    }
    
    return nil;
}


-(void) getCurrentTelephonyStatus {
    // Telephony Icon on app menu.
    CallForwardType type = CallForwardTypeNone;
    TelephonyStatus reactTelephontSatus;
    if([ServicesManager sharedInstance].myUser.callForwardStatus) {
        type = [ServicesManager sharedInstance].myUser.callForwardStatus.callForwardType;
    }
    
    if(type == CallForwardTypeBusyOrNoReply) {
        reactTelephontSatus = Forward_Voicemail;
    }
    else if (type == CallForwardTypeNone) {
        reactTelephontSatus = Forward_Phonenumber;
    }
    else{
        if (_myUser.nomadicStatus.activated) {
            reactTelephontSatus = Nomadic_Activated;
        }
        else{
            reactTelephontSatus = Nomadic_Dctivated;
        }
    }
    
    NSLog(@"[Telephony] getCurrentTelephonyStatus with status: %@",reactTelephontSatus);
    [self sendEventWithName:TelephonyStatusUpdated eventBody:reactTelephontSatus];
}

-(void) getCurrentForwardStatus {
    
    TelephonyStatus callForwardStatus;
    switch (_myUser.callForwardStatus.callForwardType) {
        case CallForwardTypeNone:
        {
            
            NSString *destinationNumber = _myUser.callForwardStatus.destination.numberE164;
            
            if ([destinationNumber isEqualToString:_myUserPersonalPhone.numberE164]) {
                callForwardStatus = TelephonyForwardPersonalPhone ;
            }
            else if ([destinationNumber isEqualToString:_myUserPersonalMobile.numberE164]){
                callForwardStatus = TelephonyForwardPersonalMobile ;
            }
            else if ([destinationNumber isEqualToString:_myUserWorkMobile.numberE164]){
                callForwardStatus = TelephonyForwardWorkMobile ;
            }
            else {
                callForwardStatus = TelephonyForwardOtherNumber ;
            }
            [self sendEventWithName:CallForwardNumberDestination eventBody:destinationNumber];
        }
            break;
            
//        case CallForwardTypeVoicemail:
//            callForwardStatus = TelephonyForwardVoicemail;
//            break;
            
        default:
            callForwardStatus = TelephonyForwardCancel;
            break;
    }
    NSLog(@"[Telephony] getCurrentForwardStatus: %@",callForwardStatus);
    
    [self sendEventWithName:CallForwardStatus eventBody:callForwardStatus];
}

-(void) getForwardAvailableOptions {
    NSMutableArray *forwardDialogOptions = [[NSMutableArray alloc] init];
    NSString *voiceMailNumber = _myUser.voiceMailNumber;
    
    if (_myUserWorkMobile) {//TODO: add this later
        //    [forwardDialogOptions addObject:TelephonyForwardWorkMobile];
    }
    if (_myUserPersonalMobile) {
        [forwardDialogOptions addObject:TelephonyForwardPersonalMobile];
    }
    if (_myUserPersonalPhone) {
        [forwardDialogOptions addObject:TelephonyForwardPersonalPhone];
    }
    if (voiceMailNumber != nil && voiceMailNumber.length > 0) {
        [forwardDialogOptions addObject:TelephonyForwardVoicemail];
    }
    [forwardDialogOptions addObject:TelephonyForwardCancel];
    [forwardDialogOptions addObject:TelephonyForwardOtherNumber];
    
    [self sendEventWithName:CallForwardOptionsUpdated eventBody:forwardDialogOptions];
}

#pragma mark - myUser Forwarding and Nomadic status Register and unRegister Notification

-(void) registerForwaringEvent {
    NSLog(@"[Telephony]registerForwaring");
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myUserCallForwardDidUpdate:) name:kMyUserCallForwardDidUpdate object:nil];
}

-(void) registerNomadicEvent {
    NSLog(@"[Telephony]registerNomadic");
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myUserNomadicStatusDidUpdate:) name:kMyUserNomadicStatusDidUpdate object:nil];
}

-(void) unRegisterForwaringEvent {
    NSLog(@"[Telephony]unRegisterForwaringEvent");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kMyUserCallForwardDidUpdate object:nil];
}

-(void) unRegisterNomadicEvent {
    NSLog(@"[Telephony]unRegisterNomadicEvent");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kMyUserNomadicStatusDidUpdate object:nil];
}
 - ( IEventEmmiter *)eventEmitter {
     if (!_eventEmitter) {
         _eventEmitter = [self.bridge moduleForClass:[IEventEmmiter class]];
     }
     return _eventEmitter;
 }

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

@end
