//
//  RNCCMessages.m
//  RNContextCenter
//
//  Created by Shaffiulla Khan on 07/01/19.
//  Copyright © 2019 Impekable LLC. All rights reserved.
//

#import "RNCCMessages.h"
#import "RNCCChannels.h"
#import "RNCCClient.h"
#import <React/RCTUtils.h>
#import "RCTConvert+ContextCenter.h"

@interface RNCCMessages()
@end

@implementation RNCCMessages

- (void)fetchMessagesWithChannelSid:(NSString *)sid completion:(void (^)(TCHResult *result, TCHMessages *messages))completion {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        completion(result, [channel messages]);
    }];
}

- (NSArray<NSString *> *)supportedEvents {
    return @[];
}
RCT_EXPORT_MODULE(CCMessages)

RCT_REMAP_METHOD(lastConsumedMessageIndex, channelSid:(NSString *)channelSid last_message_index_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            resolve(@[RCTNullIfNil(messages.lastConsumedMessageIndex)]);
        }
        else {
            reject(@"lastConsumedMessageIndexError", @"Error occured while attempting to getLastUsedConsumptionIndex.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(sendMessage, channelSid:(NSString *)channelSid body:(NSString *)body attributes:(NSDictionary<NSString *, id> *)attributes send_message_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            NSLog(@"message: %@", body);
            TCHMessageOptions *messageOptions = [[[TCHMessageOptions new] withBody:body] withAttributes:attributes completion:^(TCHResult * _Nonnull result) {}];
            [messages sendMessageWithOptions:messageOptions completion:^(TCHResult * _Nonnull sendResult, TCHMessage * _Nullable sentMessage) {
                NSLog(@"sentMessage: %@", sentMessage.body);
                if (!sendResult.isSuccessful) {
                    NSLog(@"message not sent...");
                    reject(@"sendMessageError", @"Error occured while attempting to send a message.", sendResult.error);
                }else{
                    NSLog(@"message sent...");
                    resolve(@[@TRUE]);
                }
            }];
        }
        else {
            reject(@"sendMessageError", @"Error occured while attempting to send a message.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(removeMessage, channelSid:(NSString *)channelSid index:(NSNumber *)index remove_message_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages messageWithIndex:index completion:^(TCHResult *result, TCHMessage *message) {
                if (result.isSuccessful) {
                    [messages removeMessage:message completion:^(TCHResult *result) {
                        if (result.isSuccessful) {
                            resolve(@[@TRUE]);
                        }
                        else {
                            reject(@"removeMessageError", @"Error occured while attempting to delete a message.", result.error);
                        }
                    }];
                }
                else {
                    reject(@"removeMessageError", @"Error occured while attempting to delete a message.", result.error);
                }
            }];
        }
        else {
            reject(@"removeMessageError", @"Error occured while attempting to delete a message.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getLastMessages, channelSid:(NSString *)channelSid count:(NSUInteger)count last_messages_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages getLastMessagesWithCount:count completion:^(TCHResult *result, NSArray<TCHMessage *> *messages) {
                if (result.isSuccessful) {
                    resolve([RCTConvert messages:messages]);
                }
                else {
                    reject(@"getLastMessagesError", @"Error occured while attempting to getLastMessages.", result.error);
                }
            }];
        }
        else {
            reject(@"getLastMessagesError", @"Error occured while attempting to getLastMessages.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getMessagesBefore, channelSid:(NSString *)channelSid index:(NSUInteger)index withCount:(NSUInteger)withCount messages_before_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages getMessagesBefore:index withCount:withCount completion:^(TCHResult *result, NSArray<TCHMessage *> *messages) {
                if (result.isSuccessful) {
                    resolve([RCTConvert messages:messages]);
                }
                else {
                    reject(@"getMessagesBeforeError", @"Error occured while attempting to getMessagesBefore.", result.error);
                }
            }];
        }
        else {
            reject(@"getMessagesBeforeError", @"Error occured while attempting to getMessagesBefore.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getMessagesAfter, channelSid:(NSString *)channelSid index:(NSUInteger)index withCount:(NSUInteger)withCount messages_after_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages getMessagesAfter:index withCount:withCount completion:^(TCHResult *result, NSArray<TCHMessage *> *messages) {
                if (result.isSuccessful) {
                    resolve([RCTConvert messages:messages]);
                }
                else {
                    reject(@"getMessagesAfterError", @"Error occured while attempting to getMessagesAfter.", result.error);
                }
            }];
        }
        else {
            reject(@"getMessagesAfterError", @"Error occured while attempting to getMessagesAfter.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getMessage, channelSid:(NSString *)channelSid index:(NSNumber *)index message_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages messageWithIndex:index completion:^(TCHResult *result, TCHMessage *message) {
                if (result.isSuccessful) {
                    resolve([RCTConvert message:message]);
                }
                else {
                    reject(@"messageWithIndexError", @"Error occured while attempting to getMessage.", result.error);
                }
            }];
        }
        else {
            reject(@"messageWithIndexError", @"Error occured while attempting to getMessage.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(messageForConsumptionIndex, channelSid:(NSString *)channelSid index:(NSNumber *)index message_for_index_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages messageForConsumptionIndex:index completion:^(TCHResult *result, TCHMessage *message) {
                if (result.isSuccessful) {
                    resolve([RCTConvert message:message]);
                }
                else {
                    reject(@"messageForConsumptionIndexError", @"Error occured while attempting to getMessageForConsumptionIndex.", result.error);
                }
            }];
        }
        else {
            reject(@"messageForConsumptionIndexError", @"Error occured while attempting to getMessage.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(setLastConsumedMessageIndex, channelSid:(NSString *)channelSid set_index:(NSNumber *)index set_last_message_index_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages setLastConsumedMessageIndex:index completion:^(TCHResult * _Nonnull result, NSUInteger count) {
                if(result.isSuccessful){
                    resolve(@[@TRUE]);
                }else{
                    reject(@"setLastConsumedMessageIndexError", @"Error occured while attempting to setLastConsumedMessageIndex.", result.error);
                }
            }];
        }
        else {
            reject(@"setLastConsumedMessageIndexError", @"Error occured while attempting to setLastConsumedMessageIndex.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(advanceLastConsumedMessageIndex, channelSid:(NSString *)channelSid advance_index:(NSNumber *)index advance_message_index_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages advanceLastConsumedMessageIndex:index completion:^(TCHResult * _Nonnull result, NSUInteger count) {
                if(result.isSuccessful){
                    resolve(@[@TRUE]);
                }else{
                    reject(@"advanceLastConsumedMessageIndexError", @"Error occured while attempting to advanceLastConsumedMessageIndex.", result.error);
                }
            }];
        }
        else {
            reject(@"advanceLastConsumedMessageIndexError", @"Error occured while attempting to advanceLastConsumedMessageIndex.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(setAllMessagesConsumed, channelSid:(NSString *)channelSid message_read_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages setAllMessagesConsumedWithCompletion:^(TCHResult * _Nonnull result, NSUInteger count) {
                if(result.isSuccessful){
                    resolve(@[@TRUE]);
                }else{
                    reject(@"setAllMessagesConsumedError", @"Error occured while attempting to setAllMessagesConsumed.", result.error);
                }
            }];
        }
        else {
            reject(@"setAllMessagesConsumedError", @"Error occured while attempting to setAllMessagesConsumed.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(updateBody, channelSid:(NSString *)channelSid index:(NSNumber *)index body:(NSString *)body update_body_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages messageWithIndex:index completion:^(TCHResult *result, TCHMessage *message) {
                if (result.isSuccessful) {
                    [message updateBody:body completion:^(TCHResult *result) {
                        if (result.isSuccessful) {
                            resolve(@[@TRUE]);
                        }
                        else {
                            reject(@"updateBodyError", @"Error occured while attempting to update the body of the message.", result.error);
                        }
                    }];
                }
                else {
                    reject(@"updateBodyError", @"Error occured while attempting to update the body of the message.", result.error);
                }
            }];
        }
        else {
            reject(@"updateBodyError", @"Error occured while attempting to update the body of the message.", result.error);
        }
    }];
}


RCT_REMAP_METHOD(setAttributes, channelSid:(NSString *)channelSid index:(NSNumber *)index attributes:(NSDictionary *)attributes attributes_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [self fetchMessagesWithChannelSid:channelSid completion:^(TCHResult *result, TCHMessages *messages) {
        if (result.isSuccessful) {
            [messages messageWithIndex:index completion:^(TCHResult *result, TCHMessage *message) {
                if (result.isSuccessful) {
                    [message setAttributes:attributes completion:^(TCHResult *result) {
                        if (result.isSuccessful) {
                            resolve(@[@TRUE]);
                        }
                        else {
                            reject(@"setAttributesError", @"Error occured while attempting to set attributes of the message.", result.error);
                        }
                    }];
                }
                else {
                    reject(@"setAttributesError", @"Error occured while attempting to set attributes of the message.", result.error);
                }
            }];
        }
        else {
            reject(@"setAttributesError", @"Error occured while attempting to set attributes of the message.", result.error);
        }
    }];
}
@end