/******************************************************************************/
/*                                                                            */
/* Copyright Avaya LLC.                                                       */
/*                                                                            */
/******************************************************************************/

#import "ActiveCallViewController.h"
#import "NotificationHelper.h"
#import "SDKManager.h"
#import "ConferenceControlViewController.h"
#import "ConfigData.h"

@interface ActiveCallViewController () <NSWindowDelegate>

@property (nonatomic) BOOL contentSharingActive;
@property (nonatomic, weak) CSCollaboration *collaboration;
@property (nonatomic, weak) CSContentSharing *contentSharing;
@property (nonatomic, strong) ContentSharingViewController *sharingViewController;
@property (nonatomic, strong) NSWindowController *collaborationWindowController;
@property (nonatomic, weak) NSTimer *callTimer;
@property (nonatomic) BOOL viewInitialized;
@property (nonatomic, weak) MediaManager* mediaManager;

@end

@implementation ActiveCallViewController

@synthesize localVideoView;
@synthesize remoteVideoView;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.viewInitialized = NO;
    self.contentSharingActive = NO;
    self.mediaManager = [SDKManager getInstance].mediaManager;
    // Change window background to white
    self.view.wantsLayer = YES;
    self.view.layer.backgroundColor = [NSColor whiteColor].CGColor;
    
    NSLog(@"%s Received call object from segue: [%@]", __PRETTY_FUNCTION__, self.currentCall);
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshActiveCallWindow:) name:kRefreshActiveCallWindowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(collaborationStartedNotification:) name:kCollaborationStartedNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(collabServiceStatusUpdated:) name:kCollaborationServiceStatusUpdated object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentSharingStarted:) name:kContentSharingStartedByParticipant object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(collabSessionEndedRemotely:) name:kCollaborationSessionEndedRemotely object:nil];
    
    // Display current call status
    self.callState.stringValue = @"";
    
    if (self.currentCall.isConference) {
        
        NSLog(@"%s Call is Conference call, populate participant list", __PRETTY_FUNCTION__);
        NSArray *participantsNames = [self.currentCall.conference.participants valueForKey:@"displayName"];
        self.participantList.stringValue = [participantsNames componentsJoinedByString:@"\n"];

        self.conferenceControlBtn.hidden = !self.currentCall.conference.moderationCapability.allowed;
    } else if (self.currentCall.callerIdentityPrivate) {
        
        NSLog(@"%s Call identitiy is private", __PRETTY_FUNCTION__);
        self.participantList.stringValue = @"Restricted";
    } else {
        
        NSLog(@"%s Update caller display name", __PRETTY_FUNCTION__);
        if (self.currentCall.remoteDisplayName.length == 0) {
            
            // Display remoteNumber if remoteDisplayName is unavailable
            self.participantList.stringValue = [NSString stringWithFormat:@"%@", self.currentCall.remoteNumber];
        } else {
            
            self.participantList.stringValue = [NSString stringWithFormat:@"%@", self.currentCall.remoteDisplayName];
        }
    }
    
    self.dtmf.delegate = self;
}

- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kRefreshActiveCallWindowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kCollaborationStartedNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kCollaborationServiceStatusUpdated object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kContentSharingStartedByParticipant object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kCollaborationSessionEndedRemotely object:nil];
}

- (void)viewDidDisappear {
    
    [super viewDidDisappear];
    // Release video resources
    [self deallocViews];
}

- (IBAction)endCallBtn:(id)sender {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [self.currentCall end];
}

- (IBAction)muteCallBtn:(id)sender {
    
    if (!self.currentCall.audioMuted) {
        
        if (self.currentCall.muteCapability.allowed) {
            
            NSLog(@"%s Call audio can be muted", __PRETTY_FUNCTION__);
            
            [self.currentCall muteAudio: YES completionHandler:^(NSError *error) {
                
                if (error) {
                    
                    [NotificationHelper displayMessageToUser:[NSString stringWithFormat:@"Error while muting audio of call, callId: [%lu]", self.currentCall.callId] TAG:__PRETTY_FUNCTION__];
                } else {
                    
                    NSLog(@"%s Audio Mute succesfful for call, callId: [%lu]", __PRETTY_FUNCTION__, self.currentCall.callId);
                    self.mute.title = @"ON";
                }
            }];
        } else {
            
            NSLog(@"%s Call audio cannot be muted", __PRETTY_FUNCTION__);
        }
    } else {
        
        if (self.currentCall.unmuteCapability.allowed && self.currentCall.audioMuted) {
            
            NSLog(@"%s Call audio can be unmuted", __PRETTY_FUNCTION__);
            
            [self.currentCall muteAudio:NO completionHandler:^(NSError *error) {
                
                if (error) {
                    
                    [NotificationHelper displayMessageToUser:[NSString stringWithFormat:@"Error while muting Audio of the call, callId: [%ld]", (long)self.currentCall.callId] TAG: __PRETTY_FUNCTION__];
                } else {
                    
                    NSLog(@"%s Audio of call muted successfully, callId:[%lu]", __PRETTY_FUNCTION__, self.currentCall.callId);
                    self.mute.title = @"OFF";
                }
            }];
        } else {
            
            NSLog(@"%s Call audio cannot be unmuted", __PRETTY_FUNCTION__);
        }
    }
}

- (IBAction)shareDesktopBtn:(id)sender {
    
    if (self.collaboration.contentSharing.isSharingFullScreen) {
        
        NSLog(@"%s Stop full screen sharing", __PRETTY_FUNCTION__);
        self.shareDesktopBtnLabel.title = @"Start Sharing";
        [self.collaboration.contentSharing endWithCompletionHandler:^(NSError *error) {
            
            if (error) {
                
                NSLog(@"%s Error while stopping full screen sharing. Error code [%ld] - %@", __PRETTY_FUNCTION__, (long)error.code, error.localizedDescription);
                [NotificationHelper displayMessageToUser: [NSString stringWithFormat:@"Error while stopping full screen sharing. Error code [%ld] - %@", (long)error.code, error.localizedDescription] TAG:__PRETTY_FUNCTION__];
            } else {
                
                NSLog(@"%s Successfully stopped sharing full screen", __PRETTY_FUNCTION__);
            }
        }];
    } else {
        
        NSLog(@"%s Start full screen sharing", __PRETTY_FUNCTION__);
        self.shareDesktopBtnLabel.title = @"Stop Sharing";
        
        // Get all displays which are available for sharing
        NSArray *displays = [self.collaboration.contentSharing.availableDisplays allValues];
        NSInteger displayID = -1;
        
        if (displays.count > 0) {
            
            // Share first display from availableDisplays
            displayID = ((CSSharingDisplay *)displays.firstObject).displayId;
        } else {
            
            NSLog(@"%s Error - no display available for sharing", __PRETTY_FUNCTION__);
        }
        [self.collaboration.contentSharing startSharingFullScreenWithScreenId:displayID completionHandler:^(NSError *error) {
            
            if (error) {
                
                NSLog(@"%s Error while sharing full screen. Error code [%ld] - %@", __PRETTY_FUNCTION__, (long)error.code, error.localizedDescription);
                [NotificationHelper displayMessageToUser: [NSString stringWithFormat:@"Error while sharing full screen. Error code [%ld] - %@", (long)error.code, error.localizedDescription] TAG:__PRETTY_FUNCTION__];
            } else {
                
                NSLog(@"%s Successfully started sharing full screen", __PRETTY_FUNCTION__);
            }
        }];
    }
}

// Presents Content Sharing Window
-(void) presentCollaborationWindow {
    
    NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
    self.collaborationWindowController = [storyBoard instantiateControllerWithIdentifier:@"collaborationWindowController"];
    self.sharingViewController = [storyBoard instantiateControllerWithIdentifier:@"ContentSharingViewController"];
    self.sharingViewController.contentSharing = self.contentSharing;
    self.sharingViewController.collab = self.collaboration;
    
    self.collaborationWindowController.contentViewController = self.sharingViewController;
    
    self.contentSharingActive = YES;
    [self.collaborationWindowController showWindow:self];
    self.collaborationWindowController.window.delegate = self;
}

// Update active call window when content sharing window is closed by user or when remote end stops content sharing
- (void)windowWillClose:(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    if (self.contentSharingActive) {
        
        NSLog(@"%s Content Sharing from remote participant is active", __PRETTY_FUNCTION__);
        self.sharingViewController = nil;
        self.collaborationBtnLabel.hidden = NO;
        self.shareDesktopBtnLabel.hidden = YES;
    } else {
        
        NSLog(@"%s Content Sharing from remote participant is not active", __PRETTY_FUNCTION__);
        self.sharingViewController = nil;
        self.collaborationBtnLabel.hidden = YES;
        self.shareDesktopBtnLabel.hidden = NO;
    }
}

// Re-opens Content Sharing window
- (IBAction)collaborationBtn:(id)sender {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    self.collaborationBtnLabel.hidden = YES;
    self.shareDesktopBtnLabel.hidden = NO;
    [self presentCollaborationWindow];
}

-(void) contentSharingStarted :(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    if (notification.object) {
        self.contentSharing = notification.object;
        [self presentCollaborationWindow];
    }
}

- (void)collaborationStartedNotification:(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    self.collaboration = notification.object;
}

- (void)collabSessionEndedRemotely:(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    self.shareDesktopBtnLabel.title = @"Start Sharing";
    self.collaborationBtnLabel.hidden = YES;
    
    if (self.collaborationWindowController.isWindowLoaded) {
        
        self.contentSharingActive = NO;
        [self.collaborationWindowController close];
    }
}

- (void)collabServiceStatusUpdated:(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    self.collaboration = self.collaboration = notification.object;
    self.shareDesktopBtnLabel.hidden = !self.collaboration.contentSharingCapability.allowed;
    
    if (self.collaboration.contentSharing.isSharingFullScreen ||
        self.collaboration.contentSharing.isSharingScreenRegion ||
        self.collaboration.contentSharing.isSharingApplicationWindow) {
        
        NSLog(@"%s collaboration already active", __PRETTY_FUNCTION__);
        self.shareDesktopBtnLabel.title = @"Stop Sharing";
    } else {
        
        NSLog(@"%s collaboration not active", __PRETTY_FUNCTION__);
        self.shareDesktopBtnLabel.title = @"Start Sharing";
    }
}


- (void)refreshActiveCallWindow:(NSNotification *)notification {
    
    // Check if video channels are available for call, if Yes then display local and remote video previews
    if (self.currentCall.videoChannels.count != 0) {
        
        NSLog(@"%s call has Video", __PRETTY_FUNCTION__);
        [self initViews];
    } else {
        
        NSLog(@"%s call doesn't have Video", __PRETTY_FUNCTION__);
        [self deallocViews];
    }
    
    NSString *state = @"";
    
    // Determine current call state
    switch ([self.currentCall state]) {
        case CSCallStateIdle:
            state = @"Idle";
            break;
        case CSCallStateInitiating:
            state = @"Initiating";
            break;
        case CSCallStateAlerting:
            state = @"Alerting";
            break;
        case CSCallStateRemoteAlerting:
            state = @"Remote Alerting";
            break;
        case CSCallStateEstablished:
        {
            state = @"Established";
            [self.callTimer invalidate];
            
            self.callTimer = [NSTimer scheduledTimerWithTimeInterval:1
                                                              target:self selector:@selector(callTimer:)
                                                            userInfo:nil repeats:YES];
            break;
        }
        case CSCallStateHolding:
            state = @"Holding";
            break;
        case CSCallStateHeld:
            state = @"Held";
            break;
        case CSCallStateUnholding:
            state = @"Unholding";
            break;
        case CSCallStateVideoUpdating:
            state = @"Video Updating";
            break;
        case CSCallStateTransferring:
            state = @"Transferring";
            break;
        case CSCallStateBeingTransferred:
            state = @"Being Transferred";
            break;
        case CSCallStateIgnored:
            state = @"Ignored";
            break;
        case CSCallStateFailed:
        {
            state = @"Failed";
            // End call timer
            [self.callTimer invalidate];
            [self deallocViews];
            [self dismissController:self];
            break;
        }
        case CSCallStateEnding:
            state = @"Ending";
            break;
        case CSCallStateEnded:
        {
            state = @"Ended";
            // End call timer
            [self.callTimer invalidate];
            [self deallocViews];
            if (self.collaborationWindowController.isWindowLoaded) {
                
                self.contentSharingActive = NO;
                [self.collaborationWindowController close];
            }
            [self dismissController:self];
            break;
        }
        case CSCallStateRenegotiating:
            state = @"Renegotiating";
            break;
        case CSCallStateFarEndRenegotiating:
            state = @"Far end Renegotiating";
            break;
        default:
            state = @"Unknown";
            break;
    }
    
    // Update current call state on UI
    self.callState.stringValue = [NSString stringWithFormat:@"%@", state];
    if(self.currentCall.state != CSCallStateEnded) {
        
        // Update Participant list
        if (self.currentCall.isConference) {
            NSLog(@"%s Call is Conference call, populate participant list", __PRETTY_FUNCTION__);
            self.participantList.stringValue = @"";

            NSArray *participantsNames = [self.currentCall.conference.participants valueForKey:@"displayName"];
            self.participantList.stringValue = [participantsNames componentsJoinedByString:@"\n"];
            
            self.conferenceControlBtn.hidden = !self.currentCall.conference.moderationCapability.allowed;
        } else if (self.currentCall.callerIdentityPrivate) {
            
            NSLog(@"%s Call identitiy is private", __PRETTY_FUNCTION__);
            self.participantList.stringValue = @"Restricted";
        } else {
            
            NSLog(@"%s Update caller display name", __PRETTY_FUNCTION__);
            if (self.currentCall.remoteDisplayName.length == 0) {
                
                // Display remoteNumber if remoteDisplayName is unavailable
                self.participantList.stringValue = [NSString stringWithFormat:@"%@", self.currentCall.remoteNumber];
            } else {
                
                self.participantList.stringValue = [NSString stringWithFormat:@"%@", self.currentCall.remoteDisplayName];
            }
        }
    }
}

- (void) recievedCollaboration :(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    if (notification.object) {
        
        NSLog(@"%s CSContentSharing Object Recieved", __PRETTY_FUNCTION__);
        self.contentSharing = notification.object;
        [self presentCollaborationWindow];
    }
}

- (void)collabSessionUpdated:(NSNotification *)notification {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    self.collaboration = notification.object;
}

- (void)controlTextDidChange:(NSNotification *)obj {
    
    if (self.currentCall.sendDigitCapability.allowed) {
        
        if (self.dtmf.stringValue.length > 0) {
            
            NSString *digit = [self.dtmf.stringValue substringFromIndex:self.dtmf.stringValue.length - 1];
            NSLog(@"%s Send DTMF DIGIT: [%@]", __PRETTY_FUNCTION__, digit);
            
            NSInteger digitCode = -1;
            
            if (digit.integerValue == 0) {
                
                if ([digit compare:@"0"] == NSOrderedSame) {
                    
                    digitCode = 0;
                } else if ([digit compare:@"*"] == NSOrderedSame) {
                    
                    digitCode = 10;
                } else if ([digit compare:@"#"] == NSOrderedSame) {
                    
                    digitCode = 11;
                } else if ([digit compare:@"a" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
                    
                    digitCode = 11;
                } else if ([digit compare:@"b" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
                    
                    digitCode = 12;
                } else if ([digit compare:@"c" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
                    
                    digitCode = 13;
                } else if ([digit compare:@"d" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
                    
                    digitCode = 14;
                }
            } else {
                digitCode = digit.integerValue;
            }
            
            switch (digitCode) {
                case 0:
                    [self.currentCall sendDigit:CSDTMFToneZero];
                    break;
                case 1:
                    [self.currentCall sendDigit:CSDTMFToneOne];
                    break;
                case 2:
                    [self.currentCall sendDigit:CSDTMFToneTwo];
                    break;
                case 3:
                    [self.currentCall sendDigit:CSDTMFToneThree];
                    break;
                case 4:
                    [self.currentCall sendDigit:CSDTMFToneFour];
                    break;
                case 5:
                    [self.currentCall sendDigit:CSDTMFToneFive];
                    break;
                case 6:
                    [self.currentCall sendDigit:CSDTMFToneSix];
                    break;
                case 7:
                    [self.currentCall sendDigit:CSDTMFToneSeven];
                    break;
                case 8:
                    [self.currentCall sendDigit:CSDTMFToneEight];
                    break;
                case 9:
                    [self.currentCall sendDigit:CSDTMFToneNine];
                    break;
                case 10:
                    [self.currentCall sendDigit:CSDTMFToneStar];
                    break;
                case 11:
                    [self.currentCall sendDigit:CSDTMFTonePound];
                    break;
                case 12:
                    [self.currentCall sendDigit:CSDTMFToneA];
                    break;
                case 13:
                    [self.currentCall sendDigit:CSDTMFToneB];
                    break;
                case 14:
                    [self.currentCall sendDigit:CSDTMFToneC];
                    break;
                case 15:
                    [self.currentCall sendDigit:CSDTMFToneD];
                    break;
                default:
                    NSLog(@"Not a valid DTMF character");
                    break;
            }
        }
    } else {
        
        NSLog(@"%s Client does not have capability to send DTMF", __PRETTY_FUNCTION__);
    }
}

- (NSString *)callTimerAsFormattedString {
    
    // Get elapsed time since call was established
    NSTimeInterval interval = - [self.currentCall.establishedDate timeIntervalSinceNow];
    NSString *intervalString = [[NSDateComponentsFormatter new] stringFromTimeInterval: interval];
    
    NSString *callTimerFormat;
    
    //Set correct format to hh:mm:ss
    switch(intervalString.length){
        case 1:
            callTimerFormat = @"00:00:0%@";
            break;
            
        case 2:
            callTimerFormat = @"00:00:%@";
            break;
        
        case 4:
            callTimerFormat = @"00:0%@";
            break;
            
        case 5:
            callTimerFormat = @"00:%@";
            break;
            
        case 7:
            callTimerFormat = @"0%@";
            break;
            
        default :
            callTimerFormat = @"%@";
    }
    
    return [NSString stringWithFormat:callTimerFormat, intervalString];
}

- (void)callTimer:(NSTimer*)theTimer {
    
    self.callDuration.stringValue = [self callTimerAsFormattedString];
}

- (void)initViews {
    
    // Perform initialization only once
    if (!self.viewInitialized) {
        
        [self.mediaManager initializeVideoView:self];
        self.viewInitialized = YES;
        [self.mediaManager runLocalVideo];
        
        localVideoView.wantsLayer = YES;
        localVideoView.layer = self.mediaManager.localVideoSink;
        
        remoteVideoView.wantsLayer = YES;
        remoteVideoView.layer = self.mediaManager.remoteVideoSink;
    }
    
    // Show remote video preview when call is established
    if ([self.currentCall state] == CSCallStateEstablished) {
        
        // show remote video preview
        remoteVideoView.hidden = NO;
        [self.mediaManager.remoteVideoSink handleVideoFrame:nil];
        [self.mediaManager runRemoteVideo:self.currentCall];
    }
    
    // show labels on window
    self.remoteVideoLabel.hidden = NO;
    self.localVideoLabel.hidden = NO;
    
    // show local video preview
    localVideoView.hidden = NO;
}

- (void)deallocViews {
    
    NSLog(@"%s", __PRETTY_FUNCTION__);
    if (self.viewInitialized) {
        
        // Hide local and remote video previews
        localVideoView.hidden = YES;
        remoteVideoView.hidden = YES;
        self.remoteVideoLabel.hidden = YES;
        self.localVideoLabel.hidden = YES;
        
        // Release camera resource from OS
        [self.mediaManager stopVideoCapture];
    }
}

- (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender {
    
    if ([segue.identifier isEqualToString:@"conferenceControlSegue"]) {
        ConferenceControlViewController *viewController = segue.destinationController;
        viewController.conferenceCall = self.currentCall.conference;
    }
}

@end
