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

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

@interface RNCCChannels()
@end

@implementation RNCCChannels

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

RCT_EXPORT_MODULE(CCChannels);

+ (void)fetchChannelForSid:(NSString *)sid completion:(void (^)(TCHResult *result, TCHChannel *channel))completion {
    TwilioChatClient *client = [[RNCCClient shared] twilioClient];
    [[client channelsList] channelWithSidOrUniqueName:sid completion:completion];
}

#pragma mark Channel
RCT_REMAP_METHOD(fetchUserChannels, user_channels_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    TwilioChatClient *client = [[RNCCClient shared] twilioClient];
    [[client channelsList] userChannelDescriptorsWithCompletion:^(TCHResult *result, TCHChannelDescriptorPaginator *paginator) {
        if(result.isSuccessful){
            NSString *uuid = [RNCCPaginator setPaginator:paginator];
            resolve(@{@"sid":uuid,@"type": @"UserChannel",@"paginator": [RCTConvert channelDescriptorPaginator:paginator]});
        }else{
            reject(@"fetchUserChannelsError",@"Error occured fetching user channels.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(fetchPublicChannels, public_channels_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    TwilioChatClient *client = [[RNCCClient shared] twilioClient];
    [[client channelsList] publicChannelDescriptorsWithCompletion:^(TCHResult *result, TCHChannelDescriptorPaginator *paginator) {
        if(result.isSuccessful){
            NSString *uuid = [RNCCPaginator setPaginator:paginator];
            resolve(@{@"sid":uuid,@"type": @"PublicChannel",@"paginator": [RCTConvert channelDescriptorPaginator:paginator]});
        }else{
            reject(@"fetchPublicChannelsError",@"Error occured fetching public channels.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getUserChannels, user_channel_list_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    TwilioChatClient *client = [[RNCCClient shared] twilioClient];
    resolve([RCTConvert channels:[[client channelsList] subscribedChannels]]);
}

RCT_REMAP_METHOD(createChannel, options:(NSDictionary *)options create_channel_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    TwilioChatClient *client = [[RNCCClient shared] twilioClient];
    [[client channelsList] createChannelWithOptions:options completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            resolve([RCTConvert channel:channel]);
        }
        else {
            reject(@"createChannelError", @"Error occured while creating a new channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(fetchChannel, sidOrName:(NSString *)sidOrName fetch_channel_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    TwilioChatClient *client = [[RNCCClient shared] twilioClient];
    [[client channelsList] channelWithSidOrUniqueName:sidOrName completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            resolve([RCTConvert channel:channel]);
        }
        else {
            reject(@"fetchChannelError", [NSString stringWithFormat:@"Channel could not be found with sid/uniquieName: %@.", sidOrName], result.error);
        }
    }];
}

RCT_REMAP_METHOD(synchronize, sid:(NSString *)sid sync_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            resolve(@[@TRUE]);
        }
        else {
            reject(@"synchronizeError", @"Error occured during channel syncronization.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(setAttributes, sid:(NSString *)sid attributes:(NSDictionary *)attributes attributes_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel setAttributes:attributes completion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"setAttributesError", @"Error occuring while setting attributes on channel.", result.error);
                }
            }];
        }
        else {
            reject(@"setAttributesError", @"Error occuring while setting attributes on channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(setFriendlyName, sid:(NSString *)sid name:(NSString *)name friendly_name_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel setFriendlyName:name completion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"setFriendlyNameError", @"Error occured while attempting to setFriendlyName on channel.", result.error);
                }
            }];
        }
        else {
            reject(@"setFriendlyNameError", @"Error occured while attempting to setFriendlyName on channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(setUniqueName, sid:(NSString *)sid uniqueName:(NSString *)uniqueName unique_name_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel setUniqueName:uniqueName completion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"setUniqueNameError", @"Error occured while attempting to setUniqueName on channel.", result.error);
                }
            }];
        }
        else {
            reject(@"setUniqueNameError", @"Error occured while attempting to setUniqueName on channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(joinChannel, sid:(NSString *)sid join_channel_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel joinWithCompletion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"joinChannelError", @"Error occured while attempting to join the channel.", result.error);
                }
            }];
        }
        else {
            reject(@"joinChannelError", @"Error occured while attempting to join the channel.", result.error);
        }
        
    }];
}

RCT_REMAP_METHOD(declineInvitation, sid:(NSString *)sid decline_invite_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel declineInvitationWithCompletion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"declineInvitationError", @"Error occured while attempting to decline the invitation to join the channel.", result.error);
                }
            }];
        }
        else {
            reject(@"declineInvitationError", @"Error occured while attempting to decline the invitation to join the channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(leaveChannel, sid:(NSString *)sid leave_channel_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel leaveWithCompletion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"leaveChannelError", @"Error occured while attempting to leave the channel.", result.error);
                }
            }];
        }
        else {
            reject(@"leaveChannelError", @"Error occured while attempting to leave the channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(deleteChannel, sid:(NSString *)sid delete_channel_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel destroyWithCompletion:^(TCHResult *result) {
                if (result.isSuccessful) {
                    resolve(@[@TRUE]);
                }
                else {
                    reject(@"deleteChannelError", @"Error occured while attempting to delete the channel.", result.error);
                }
            }];
        }
        else {
            reject(@"deleteChannelError", @"Error occured while attempting to delete the channel.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getUnconsumedMessagesCount, sid:(NSString *)sid unconsumed_message_count_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel getUnconsumedMessagesCountWithCompletion:^(TCHResult *result, NSUInteger count) {
                if (result.isSuccessful) {
                    resolve(@(count));
                }
                else {
                    reject(@"getUnconsumedMessagesCountError", @"Error occured while attempting to get Unconsumed messages count.", result.error);
                }
            }];
        }
        else {
            reject(@"getUnconsumedMessagesCountError", @"Error occured while attempting to get Unconsumed messages count.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getMessagesCount, sid:(NSString *)sid message_count_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel getMessagesCountWithCompletion:^(TCHResult *result, NSUInteger count) {
                if (result.isSuccessful) {
                    resolve(@(count));
                }
                else {
                    reject(@"getMessagesCountError", @"Error occured while attempting to get message count.", result.error);
                }
            }];
        }
        else {
            reject(@"getMessagesCountError", @"Error occured while attempting to get message count.", result.error);
        }
    }];
}

RCT_REMAP_METHOD(getMembersCount, sid:(NSString *)sid members_count_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel getMembersCountWithCompletion:^(TCHResult *result, NSUInteger count) {
                if (result.isSuccessful) {
                    resolve(@(count));
                }
                else {
                    reject(@"getMembersCountError", @"Error occured while attempting to get members count.", result.error);
                }
            }];
        }
        else {
            reject(@"getMembersCountError", @"Error occured while attempting to get members count.", result.error);
        }
    }];
}



RCT_REMAP_METHOD(isTyping, sid:(NSString *)sid) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            [channel typing];
        }
    }];
}

RCT_REMAP_METHOD(getMember, sid:(NSString *)sid identity:(NSString *)identity member_resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [RNCCChannels fetchChannelForSid:sid completion:^(TCHResult *result, TCHChannel *channel) {
        if (result.isSuccessful) {
            resolve([RCTConvert member:[channel memberWithIdentity:identity]]);
        }
        else {
            reject(@"getMemberError", @"Error occured while attempting to get member.", result.error);
        }
    }];
}

@end
