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

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTLog.h>
#import "Rainbow/Rainbow.h"
#import "IEventEmmiter.h"
#import "Conversations.h"
#import "Conversation+DictRepresentation.h"
#import "ConversationEventsNames.h"
#import "IOSNotification.h"

@interface Conversations ()
@property(nonatomic,strong) ConversationsManagerService *conversationManagerService;
@property (nonatomic, strong) IEventEmmiter *eventEmitter;
@property (nonatomic, weak) RCTBridge *bridge;
@end

@implementation Conversations
RCT_EXPORT_MODULE();

- (instancetype)init {
    self = [super init];
    if (self) {
        [self registerConversationListerns];
        _conversationManagerService = [ServicesManager sharedInstance].conversationsManagerService;

    }
    return self;
}

- (void)dealloc {
    _conversationManagerService = nil;
    [self unRegisterConversationListerns];
}

#pragma mark - ReactNative_functions

RCT_EXPORT_METHOD(getConversations) {
    NSLog(@"[Conversations] getConversations react called");
    //remove the previous conversation array. in case login to another differnt account
    [self sendEventWithName:ConversationsUpdated eventBody:[[NSArray alloc] init]];
    [self proccessConversationAndSendItToReact];

}

RCT_EXPORT_METHOD(deleteConversationMessages:(NSString *)conversationJid) {
    NSLog(@"[Conversations] deleteConversationMessages with Jid: %@",conversationJid);
    Conversation *foundedConversation = [Conversations findConversationWithJId: conversationJid];
    if (foundedConversation) {
        [_conversationManagerService deleteAllMessagesForConversation:foundedConversation];
    }
}

RCT_EXPORT_METHOD(sendConversationByEmail:(NSString *)conversationJid) {
    NSLog(@"[Conversations] sendConversationByEmail with Jid: %@",conversationJid);
    Conversation *foundedConversation = [Conversations findConversationWithJId: conversationJid];
    if (foundedConversation) {
        [_conversationManagerService sendConversationByMail:foundedConversation completionHandler:^(NSError * _Nullable error) {
            if (error)
                NSLog(@"[Conversations] sendConversationByEmail failed: %@",error);
        }];
    }
}

RCT_EXPORT_METHOD(getConversationByJid:(NSString *) conversationJid){
    NSLog(@"[Conversations] getConversationByJid with Jid: %@",conversationJid);
    Conversation *foundConversation = [Conversations findConversationWithJId:conversationJid];
   
    if (foundConversation) {
        NSDictionary *conversationObject = [foundConversation conversationDictionaryRepresentation];

        [self sendEventWithName:GetConversationByJid eventBody:conversationObject];
    }else {
        NSLog(@"[Conversations] No conversation found with Jid: %@", conversationJid);
    }

}
#pragma mark - Conversation Notification

-(void)didAddConversation:(NSNotification *)notification {
    if(![NSThread isMainThread]){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self didAddConversation:notification];
        });
        return;
    }
    NSLog(@"[Conversations] didAddConversation");
    [self proccessConversationAndSendItToReact];
}

-(void)didRemoveConversation:(NSNotification *)notification {
    if(![NSThread isMainThread]){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self didRemoveConversation:notification];
        });
        return;
    }
    NSLog(@"[Conversations] didAddConversation");
    [self proccessConversationAndSendItToReact];
}

-(void)didUpdateConversation:(NSNotification *)notification {
    if(![NSThread isMainThread]){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self didUpdateConversation:notification];
        });
        return;
    }
    NSLog(@"[Conversations] didAddConversation");
    [self proccessConversationAndSendItToReact];
}

-(void)didUpdateMessagesUnreadCount:(NSNotification *)notification {
    if(![NSThread isMainThread]){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self didUpdateMessagesUnreadCount:notification];
        });
        return;
    }
    NSLog(@"[Conversations] didUpdateMessagesUnreadCount");
    [self proccessConversationAndSendItToReact];
}

-(void) didReceiveNewMessageForConversation:(NSNotification *)notification {
    if(![NSThread isMainThread]){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self  didReceiveNewMessageForConversation:notification];
        });
        return;
    }
    NSLog(@"[Conversations]  didReceiveNewMessageForConversation");
    UIApplicationState state = UIApplication.sharedApplication.applicationState;
    if (state == UIApplicationStateBackground || state == UIApplicationStateInactive) {
        //send notification to the user
        NSDictionary *obj = (NSDictionary *)notification.object;
        id<PeerProtocol> conversationAsPeer = [obj objectForKey:kConversationKey];
        Contact *conversationContact = (Contact*) conversationAsPeer;
        Message *notificationMessage = (Message*)[obj objectForKey:kMessageKey];
        if (conversationContact != nil && notificationMessage != nil) {
            if (!notificationMessage.hasBeenPresentedInPush && !notificationMessage.isOutgoing && !notificationMessage.isResentMessage) {
                [IOSNotification sendUserNotification:conversationContact.displayName notificationBody:notificationMessage.body iconBadgeNumber:_conversationManagerService.totalNbOfUnreadMessagesInAllConversations];
            }
        }
    }
}

#pragma mark - Others

+ (Conversation *)findConversationWithJId:(NSString *) conversationJid {
    for (id<PeerProtocol> item in  [[ServicesManager sharedInstance].conversationsManagerService conversations]) {
        if ([item.jid isEqual:conversationJid]) {
            NSLog(@"[Conversations] findConversationWithId with name: %@",item.jid);
            return item;
        }
    }
    NSLog(@"[Conversations] Couldn find conversation wih jid");
    return NULL;
}

-(void)proccessConversationAndSendItToReact {
    NSLog(@"[Conversations] proccessConversationAndSendItToReact");
    NSMutableArray *conversationsDic = [[NSMutableArray alloc] init];
    NSArray<Conversation*> *sortedArray = [_conversationManagerService.conversations sortedArrayUsingComparator:^NSComparisonResult(Conversation *p1, Conversation *p2) {
        NSDate *d1 = p1.lastUpdateDate;
        NSDate *d2 = p2.lastUpdateDate;
        return [d2 compare: d1];
    }];
    for (Conversation *conv in sortedArray) {
        id<PeerProtocol> peer = conv.peer;
        if ([peer conformsToProtocol:@protocol(RemotePartyProtocol)]) {
            id<RemotePartyProtocol> contactPeer = (id<RemotePartyProtocol>)peer;
            
            if(contactPeer.displayName == nil) {
                continue;
            } }
        [conversationsDic addObject:conv.conversationDictionaryRepresentation];
    }
    [self sendEventWithName:ConversationsUpdated eventBody:conversationsDic];
}

-(void)registerConversationListerns {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didAddConversation:) name:kConversationsManagerDidAddConversation object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRemoveConversation:) name:kConversationsManagerDidRemoveConversation object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateConversation:) name:kConversationsManagerDidUpdateConversation object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateMessagesUnreadCount:) name:kConversationsManagerDidUpdateMessagesUnreadCount object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveNewMessageForConversation:) name:kConversationsManagerDidReceiveNewMessageForConversation object:nil];
}

-(void)unRegisterConversationListerns {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kConversationsManagerDidAddConversation object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kConversationsManagerDidRemoveConversation object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kConversationsManagerDidUpdateConversation object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kConversationsManagerDidUpdateMessagesUnreadCount object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kConversationsManagerDidReceiveNewMessageForConversation 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(@" [Conversations] sendEventWithName: %@", eventName);
        [eventEmitter sendEvent:eventName eventBody:eventBody];
    } else {
        NSLog(@"[Conversations] sendEventWithName:  Bridge is not ready. Cannot send event: %@", eventName);
    }
}
+ (BOOL)requiresMainQueueSetup
{
    return NO;
}

@end

