//
//  ExtSdkGroupManagerWrapper.m
//  FlutterTest
//
//  Created by 杜洁鹏 on 2019/10/17.
//  Copyright © 2019 Easemob. All rights reserved.
//

#import "ExtSdkGroupManagerWrapper.h"

#import "ExtSdkToJson.h"

#import "ExtSdkMethodTypeObjc.h"

@interface ExtSdkGroupManagerWrapper () <AgoraChatGroupManagerDelegate>

@end

@implementation ExtSdkGroupManagerWrapper

+ (nonnull instancetype)getInstance {
    static ExtSdkGroupManagerWrapper *instance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
      instance = [[ExtSdkGroupManagerWrapper alloc] init];
    });
    return instance;
}

- (void)initSdk {
    [AgoraChatClient.sharedClient.groupManager removeDelegate:self];
    [AgoraChatClient.sharedClient.groupManager addDelegate:self delegateQueue:nil];
}

#pragma mark - Actions

- (void)getGroupWithId:(NSDictionary *)param
        withMethodType:(NSString *)aChannelName
                result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    AgoraChatGroup *group = [AgoraChatGroup groupWithId:param[@"groupId"]];
    [weakSelf onResult:result
        withMethodType:aChannelName
             withError:nil
            withParams:[group toJsonObject]];
}

- (void)getJoinedGroups:(NSDictionary *)param
         withMethodType:(NSString *)aChannelName
                 result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    NSArray *joinedGroups =
        [AgoraChatClient.sharedClient.groupManager getJoinedGroups];
    NSMutableArray *list = [NSMutableArray array];
    for (AgoraChatGroup *group in joinedGroups) {
        [list addObject:[group toJsonObject]];
    }
    [weakSelf onResult:result
        withMethodType:aChannelName
             withError:nil
            withParams:list];
}

- (void)getGroupsWithoutPushNotification:(NSDictionary *)param
                          withMethodType:(NSString *)aChannelName
                                  result:
                                      (nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    AgoraChatError *error = nil;
    NSArray *groups = [AgoraChatClient.sharedClient.groupManager
        getGroupsWithoutPushNotification:&error];
    NSMutableArray *list = [NSMutableArray array];
    for (AgoraChatGroup *group in groups) {
        [list addObject:[group toJsonObject]];
    }
    [weakSelf onResult:result
        withMethodType:aChannelName
             withError:error
            withParams:list];
}

- (void)getJoinedGroupsFromServer:(NSDictionary *)param
                   withMethodType:(NSString *)aChannelName
                           result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    int pageNum = [param[@"pageNum"] intValue];
    int pageSize = [param[@"pageSize"] intValue];
    BOOL needRole = [param[@"needRole"] boolValue];
    BOOL needMemberCount = [param[@"needMemberCount"] boolValue];
    [AgoraChatClient.sharedClient.groupManager
        getJoinedGroupsFromServerWithPage:pageNum
                                 pageSize:pageSize
                          needMemberCount:needMemberCount
                                 needRole:needRole
                               completion:^(NSArray<AgoraChatGroup *> *aList,
                                            AgoraChatError *_Nullable aError) {
                                 NSMutableArray *list = [NSMutableArray array];
                                 for (AgoraChatGroup *group in aList) {
                                     [list addObject:[group toJsonObject]];
                                 }
                                 [weakSelf onResult:result
                                     withMethodType:aChannelName
                                          withError:aError
                                         withParams:list];
                               }];
}

- (void)getPublicGroupsFromServer:(NSDictionary *)param
                   withMethodType:(NSString *)aChannelName
                           result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getPublicGroupsFromServerWithCursor:param[@"cursor"]
                                   pageSize:[param[@"pageSize"] integerValue]
                                 completion:^(AgoraChatCursorResult *aResult,
                                              AgoraChatError *aError) {
                                   [weakSelf onResult:result
                                       withMethodType:aChannelName
                                            withError:aError
                                           withParams:[aResult toJsonObject]];
                                 }];
}

- (void)createGroup:(NSDictionary *)param
     withMethodType:(NSString *)aChannelName
             result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        createGroupWithSubject:param[@"groupName"]
                   description:param[@"desc"]
                      invitees:param[@"inviteMembers"]
                       message:param[@"inviteReason"]
                       setting:[AgoraChatGroupOptions fromJsonObject:param[@"options"]]
                    completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                      [weakSelf onResult:result
                          withMethodType:aChannelName
                               withError:aError
                              withParams:[aGroup toJsonObject]];
                    }];
}

- (void)getGroupSpecificationFromServer:(NSDictionary *)param
                         withMethodType:(NSString *)aChannelName
                                 result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    NSString *groupId = param[@"groupId"];
    BOOL hasFetchMembers = NO;
    BOOL fetchMembers = NO;
    if (param[@"fetchMembers"]) {
        fetchMembers = [param[@"fetchMembers"] boolValue];
        hasFetchMembers = YES;
    }
    if (hasFetchMembers) {
        [AgoraChatClient.sharedClient.groupManager
            getGroupSpecificationFromServerWithId:groupId
                                     fetchMembers:fetchMembers
                                       completion:^(AgoraChatGroup *aGroup,
                                                    AgoraChatError *aError) {
                                         [weakSelf onResult:result
                                             withMethodType:aChannelName
                                                  withError:aError
                                                 withParams:[aGroup
                                                                toJsonObject]];
                                       }];
    } else {
        [AgoraChatClient.sharedClient.groupManager
            getGroupSpecificationFromServerWithId:groupId
                                       completion:^(AgoraChatGroup *aGroup,
                                                    AgoraChatError *aError) {
                                         [weakSelf onResult:result
                                             withMethodType:aChannelName
                                                  withError:aError
                                                 withParams:[aGroup
                                                                toJsonObject]];
                                       }];
    }
}

- (void)getGroupMemberListFromServer:(NSDictionary *)param
                      withMethodType:(NSString *)aChannelName
                              result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getGroupMemberListFromServerWithId:param[@"groupId"]
                                    cursor:param[@"cursor"]
                                  pageSize:[param[@"pageSize"] intValue]
                                completion:^(AgoraChatCursorResult *aResult,
                                             AgoraChatError *aError) {
                                  [weakSelf onResult:result
                                      withMethodType:aChannelName
                                           withError:aError
                                          withParams:[aResult toJsonObject]];
                                }];
}

- (void)getGroupBlockListFromServer:(NSDictionary *)param
                     withMethodType:(NSString *)aChannelName
                             result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getGroupBlacklistFromServerWithId:param[@"groupId"]
                               pageNumber:[param[@"pageNum"] intValue]
                                 pageSize:[param[@"pageSize"] intValue]
                               completion:^(NSArray *aList, AgoraChatError *aError) {
                                 [weakSelf onResult:result
                                     withMethodType:aChannelName
                                          withError:aError
                                         withParams:aList];
                               }];
}

- (void)getGroupMuteListFromServer:(NSDictionary *)param
                    withMethodType:(NSString *)aChannelName
                            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getGroupMuteListFromServerWithId:param[@"groupId"]
                              pageNumber:[param[@"pageNum"] intValue]
                                pageSize:[param[@"pageSize"] intValue]
                              completion:^(NSArray *aList, AgoraChatError *aError) {
                                [weakSelf onResult:result
                                    withMethodType:aChannelName
                                         withError:aError
                                        withParams:aList];
                              }];
}

- (void)getGroupWhiteListFromServer:(NSDictionary *)param
                     withMethodType:(NSString *)aChannelName
                             result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getGroupWhiteListFromServerWithId:param[@"groupId"]
                               completion:^(NSArray *aList, AgoraChatError *aError) {
                                 [weakSelf onResult:result
                                     withMethodType:aChannelName
                                          withError:aError
                                         withParams:aList];
                               }];
}

- (void)isMemberInWhiteListFromServer:(NSDictionary *)param
                       withMethodType:(NSString *)aChannelName
                               result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        isMemberInWhiteListFromServerWithGroupId:param[@"groupId"]
                                      completion:^(BOOL inWhiteList,
                                                   AgoraChatError *aError) {
                                        [weakSelf onResult:result
                                            withMethodType:aChannelName
                                                 withError:aError
                                                withParams:@(inWhiteList)];
                                      }];
}

- (void)getGroupFileListFromServer:(NSDictionary *)param
                    withMethodType:(NSString *)aChannelName
                            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getGroupFileListWithId:param[@"groupId"]
                    pageNumber:[param[@"pageNum"] intValue]
                      pageSize:[param[@"pageSize"] intValue]
                    completion:^(NSArray *aList, AgoraChatError *aError) {
                      NSMutableArray *array = [NSMutableArray array];
                      for (AgoraChatGroupSharedFile *file in aList) {
                          [array addObject:[file toJsonObject]];
                      }
                      [weakSelf onResult:result
                          withMethodType:aChannelName
                               withError:aError
                              withParams:array];
                    }];
}

- (void)getGroupAnnouncementFromServer:(NSDictionary *)param
                        withMethodType:(NSString *)aChannelName
                                result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getGroupAnnouncementWithId:param[@"groupId"]
                        completion:^(NSString *aAnnouncement, AgoraChatError *aError) {
                          [weakSelf onResult:result
                              withMethodType:aChannelName
                                   withError:aError
                                  withParams:aAnnouncement];
                        }];
}

- (void)addMembers:(NSDictionary *)param
    withMethodType:(NSString *)aChannelName
            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        addMembers:param[@"members"]
           toGroup:param[@"groupId"]
           message:param[@"welcome"]
        completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
          [weakSelf onResult:result
              withMethodType:aChannelName
                   withError:aError
                  withParams:[aGroup toJsonObject]];
        }];
}

- (void)inviterUser:(NSDictionary *)param
     withMethodType:(NSString *)aChannelName
             result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        addMembers:param[@"members"]
           toGroup:param[@"groupId"]
           message:param[@"reason"]
        completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
          [weakSelf onResult:result
              withMethodType:aChannelName
                   withError:aError
                  withParams:[aGroup toJsonObject]];
        }];
}

- (void)removeMembers:(NSDictionary *)param
       withMethodType:(NSString *)aChannelName
               result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        removeMembers:param[@"members"]
            fromGroup:param[@"groupId"]
           completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
             [weakSelf onResult:result
                 withMethodType:aChannelName
                      withError:aError
                     withParams:[aGroup toJsonObject]];
           }];
}

- (void)blockMembers:(NSDictionary *)param
      withMethodType:(NSString *)aChannelName
              result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        blockMembers:param[@"members"]
           fromGroup:param[@"groupId"]
          completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
            [weakSelf onResult:result
                withMethodType:aChannelName
                     withError:aError
                    withParams:[aGroup toJsonObject]];
          }];
}

- (void)unblockMembers:(NSDictionary *)param
        withMethodType:(NSString *)aChannelName
                result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        unblockMembers:param[@"members"]
             fromGroup:param[@"groupId"]
            completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
              [weakSelf onResult:result
                  withMethodType:aChannelName
                       withError:aError
                      withParams:[aGroup toJsonObject]];
            }];
}

- (void)updateGroupSubject:(NSDictionary *)param
            withMethodType:(NSString *)aChannelName
                    result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        updateGroupSubject:param[@"name"]
                  forGroup:param[@"groupId"]
                completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                  [weakSelf onResult:result
                      withMethodType:aChannelName
                           withError:aError
                          withParams:[aGroup toJsonObject]];
                }];
}

- (void)updateDescription:(NSDictionary *)param
           withMethodType:(NSString *)aChannelName
                   result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        updateDescription:param[@"desc"]
                 forGroup:param[@"groupId"]
               completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                 [weakSelf onResult:result
                     withMethodType:aChannelName
                          withError:aError
                         withParams:[aGroup toJsonObject]];
               }];
}

- (void)leaveGroup:(NSDictionary *)param
    withMethodType:(NSString *)aChannelName
            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager leaveGroup:param[@"groupId"]
                                        completion:^(AgoraChatError *aError) {
                                          [weakSelf onResult:result
                                              withMethodType:aChannelName
                                                   withError:aError
                                                  withParams:nil];
                                        }];
}

- (void)destroyGroup:(NSDictionary *)param
      withMethodType:(NSString *)aChannelName
              result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager destroyGroup:param[@"groupId"]
                                    finishCompletion:^(AgoraChatError *aError) {
                                      [weakSelf onResult:result
                                          withMethodType:aChannelName
                                               withError:aError
                                              withParams:nil];
                                    }];
}

- (void)blockGroup:(NSDictionary *)param
    withMethodType:(NSString *)aChannelName
            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        blockGroup:param[@"groupId"]
        completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
          [weakSelf onResult:result
              withMethodType:aChannelName
                   withError:aError
                  withParams:[aGroup toJsonObject]];
        }];
}

- (void)unblockGroup:(NSDictionary *)param
      withMethodType:(NSString *)aChannelName
              result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        unblockGroup:param[@"groupId"]
          completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
            [weakSelf onResult:result
                withMethodType:aChannelName
                     withError:aError
                    withParams:[aGroup toJsonObject]];
          }];
}

- (void)updateGroupOwner:(NSDictionary *)param
          withMethodType:(NSString *)aChannelName
                  result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        updateGroupOwner:param[@"groupId"]
                newOwner:param[@"owner"]
              completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                [weakSelf onResult:result
                    withMethodType:aChannelName
                         withError:aError
                        withParams:[aGroup toJsonObject]];
              }];
}

- (void)addAdmin:(NSDictionary *)param
    withMethodType:(NSString *)aChannelName
            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
          addAdmin:param[@"admin"]
           toGroup:param[@"groupId"]
        completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
          [weakSelf onResult:result
              withMethodType:aChannelName
                   withError:aError
                  withParams:[aGroup toJsonObject]];
        }];
}

- (void)removeAdmin:(NSDictionary *)param
     withMethodType:(NSString *)aChannelName
             result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        removeAdmin:param[@"admin"]
          fromGroup:param[@"groupId"]
         completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
           [weakSelf onResult:result
               withMethodType:aChannelName
                    withError:aError
                   withParams:[aGroup toJsonObject]];
         }];
}

- (void)muteMembers:(NSDictionary *)param
     withMethodType:(NSString *)aChannelName
             result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
             muteMembers:param[@"members"]
        muteMilliseconds:[param[@"duration"] integerValue]
               fromGroup:param[@"groupId"]
              completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                [weakSelf onResult:result
                    withMethodType:aChannelName
                         withError:aError
                        withParams:[aGroup toJsonObject]];
              }];
}

- (void)unMuteMembers:(NSDictionary *)param
       withMethodType:(NSString *)aChannelName
               result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        unmuteMembers:param[@"members"]
            fromGroup:param[@"groupId"]
           completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
             [weakSelf onResult:result
                 withMethodType:aChannelName
                      withError:aError
                     withParams:[aGroup toJsonObject]];
           }];
}

- (void)muteAllMembers:(NSDictionary *)param
        withMethodType:(NSString *)aChannelName
                result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        muteAllMembersFromGroup:param[@"groupId"]
                     completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                       [weakSelf onResult:result
                           withMethodType:aChannelName
                                withError:aError
                               withParams:[aGroup toJsonObject]];
                     }];
}

- (void)unMuteAllMembers:(NSDictionary *)param
          withMethodType:(NSString *)aChannelName
                  result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        unmuteAllMembersFromGroup:param[@"groupId"]
                       completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                         [weakSelf onResult:result
                             withMethodType:aChannelName
                                  withError:aError
                                 withParams:[aGroup toJsonObject]];
                       }];
}

- (void)addWhiteList:(NSDictionary *)param
      withMethodType:(NSString *)aChannelName
              result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        addWhiteListMembers:param[@"members"]
                  fromGroup:param[@"groupId"]
                 completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                   [weakSelf onResult:result
                       withMethodType:aChannelName
                            withError:aError
                           withParams:[aGroup toJsonObject]];
                 }];
}

- (void)removeWhiteList:(NSDictionary *)param
         withMethodType:(NSString *)aChannelName
                 result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        removeWhiteListMembers:param[@"members"]
                     fromGroup:param[@"groupId"]
                    completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                      [weakSelf onResult:result
                          withMethodType:aChannelName
                               withError:aError
                              withParams:[aGroup toJsonObject]];
                    }];
}

- (void)uploadGroupSharedFile:(NSDictionary *)param
               withMethodType:(NSString *)aChannelName
                       result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    NSString *groupId = param[@"groupId"];
    NSString *filePath = param[@"filePath"];
    [AgoraChatClient.sharedClient.groupManager uploadGroupSharedFileWithId:groupId
        filePath:filePath
        progress:^(int progress) {
          [weakSelf onReceive:ExtSdkMethodKeyUploadGroupSharedFile
                   withParams:@{
                       @"progress" : @(progress),
                       @"groupId" : groupId,
                       @"filePath" : filePath,
                       @"callbackType" : ExtSdkMethodKeyOnMessageProgressUpdate
                   }];
        }
        completion:^(AgoraChatGroupSharedFile *aSharedFile, AgoraChatError *aError) {
          if (aError) {
              [weakSelf onReceive:ExtSdkMethodKeyUploadGroupSharedFile
                       withParams:@{
                           @"error" : [aError toJsonObject],
                           @"groupId" : groupId,
                           @"filePath" : filePath,
                           @"callbackType" : ExtSdkMethodKeyOnMessageError
                       }];
          } else {
              [weakSelf onReceive:ExtSdkMethodKeyUploadGroupSharedFile
                       withParams:@{
                           @"groupId" : groupId,
                           @"filePath" : filePath,
                           @"callbackType" : ExtSdkMethodKeyOnMessageSuccess
                       }];
          }
        }];
    [self onResult:result
        withMethodType:aChannelName
             withError:nil
            withParams:nil];
}

- (void)downloadGroupSharedFile:(NSDictionary *)param
                 withMethodType:(NSString *)aChannelName
                         result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    NSString *groupId = param[@"groupId"];
    NSString *savePath = param[@"savePath"];
    NSString *fileId = param[@"fileId"];
    [AgoraChatClient.sharedClient.groupManager downloadGroupSharedFileWithId:groupId
        filePath:savePath
        sharedFileId:fileId
        progress:^(int progress) {
          [weakSelf onReceive:ExtSdkMethodKeyDownloadGroupSharedFile
                   withParams:@{
                       @"progress" : @(progress),
                       @"groupId" : groupId,
                       @"filePath" : savePath,
                       @"callbackType" : ExtSdkMethodKeyOnMessageProgressUpdate
                   }];
        }
        completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
          if (aError) {
              [weakSelf onReceive:ExtSdkMethodKeyDownloadGroupSharedFile
                       withParams:@{
                           @"error" : [aError toJsonObject],
                           @"groupId" : groupId,
                           @"filePath" : savePath,
                           @"callbackType" : ExtSdkMethodKeyOnMessageError
                       }];
          } else {
              [weakSelf onReceive:ExtSdkMethodKeyDownloadGroupSharedFile
                       withParams:@{
                           @"groupId" : groupId,
                           @"filePath" : savePath,
                           @"callbackType" : ExtSdkMethodKeyOnMessageSuccess
                       }];
          }
        }];
    [self onResult:result
        withMethodType:aChannelName
             withError:nil
            withParams:nil];
}

- (void)removeGroupSharedFile:(NSDictionary *)param
               withMethodType:(NSString *)aChannelName
                       result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        removeGroupSharedFileWithId:param[@"groupId"]
                       sharedFileId:param[@"fileId"]
                         completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                           [weakSelf onResult:result
                               withMethodType:aChannelName
                                    withError:aError
                                   withParams:@(!aError)];
                         }];
}

- (void)updateGroupAnnouncement:(NSDictionary *)param
                 withMethodType:(NSString *)aChannelName
                         result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        updateGroupAnnouncementWithId:param[@"groupId"]
                         announcement:param[@"announcement"]
                           completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                             [weakSelf onResult:result
                                 withMethodType:aChannelName
                                      withError:aError
                                     withParams:[aGroup toJsonObject]];
                           }];
}

- (void)updateGroupExt:(NSDictionary *)param
        withMethodType:(NSString *)aChannelName
                result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        updateGroupExtWithId:param[@"groupId"]
                         ext:param[@"ext"]
                  completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                    [weakSelf onResult:result
                        withMethodType:aChannelName
                             withError:aError
                            withParams:[aGroup toJsonObject]];
                  }];
}

- (void)joinPublicGroup:(NSDictionary *)param
         withMethodType:(NSString *)aChannelName
                 result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        joinPublicGroup:param[@"groupId"]
             completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
               [weakSelf onResult:result
                   withMethodType:aChannelName
                        withError:aError
                       withParams:[aGroup toJsonObject]];
             }];
}

- (void)requestToJoinPublicGroup:(NSDictionary *)param
                  withMethodType:(NSString *)aChannelName
                          result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        requestToJoinPublicGroup:param[@"groupId"]
                         message:param[@"reason"]
                      completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                        [weakSelf onResult:result
                            withMethodType:aChannelName
                                 withError:aError
                                withParams:[aGroup toJsonObject]];
                      }];
}

- (void)acceptJoinApplication:(NSDictionary *)param
               withMethodType:(NSString *)aChannelName
                       result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        approveJoinGroupRequest:param[@"groupId"]
                         sender:param[@"username"]
                     completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                       [weakSelf onResult:result
                           withMethodType:aChannelName
                                withError:aError
                               withParams:[aGroup toJsonObject]];
                     }];
}

- (void)declineJoinApplication:(NSDictionary *)param
                withMethodType:(NSString *)aChannelName
                        result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        declineJoinGroupRequest:param[@"groupId"]
                         sender:param[@"username"]
                         reason:param[@"reason"]
                     completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                       [weakSelf onResult:result
                           withMethodType:aChannelName
                                withError:aError
                               withParams:[aGroup toJsonObject]];
                     }];
}

- (void)acceptInvitationFromGroup:(NSDictionary *)param
                   withMethodType:(NSString *)aChannelName
                           result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        acceptInvitationFromGroup:param[@"groupId"]
                          inviter:param[@"inviter"]
                       completion:^(AgoraChatGroup *aGroup, AgoraChatError *aError) {
                         [weakSelf onResult:result
                             withMethodType:aChannelName
                                  withError:aError
                                 withParams:[aGroup toJsonObject]];
                       }];
}

- (void)declineInvitationFromGroup:(NSDictionary *)param
                    withMethodType:(NSString *)aChannelName
                            result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        declineGroupInvitation:param[@"groupId"]
                       inviter:param[@"inviter"]
                        reason:param[@"reason"]
                    completion:^(AgoraChatError *aError) {
                      [weakSelf onResult:result
                          withMethodType:aChannelName
                               withError:aError
                              withParams:nil];
                    }];
}

- (void)setMemberAttribute:(NSDictionary *)param
            withMethodType:(NSString *)aChannelName
                    result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    NSString *groupId = param[@"groupId"];
    NSString *userId = param[@"member"];
    NSDictionary *attributes = param[@"attributes"];
    [AgoraChatClient.sharedClient.groupManager
        setMemberAttribute:groupId
                    userId:userId
                attributes:attributes
                completion:^(AgoraChatError *_Nullable error) {
                  [weakSelf onResult:result
                      withMethodType:aChannelName
                           withError:error
                          withParams:nil];
                }];
}

- (void)fetchMemberAttributes:(NSDictionary *)param
               withMethodType:(NSString *)aChannelName
                       result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;

    NSString *groupId = param[@"groupId"];
    NSString *userId = param[@"member"];

    [AgoraChatClient.sharedClient.groupManager
        fetchMemberAttribute:groupId
                      userId:userId
                  completion:^(
                      NSDictionary<NSString *, NSString *> *_Nullable data,
                      AgoraChatError *_Nullable error) {
                    [weakSelf onResult:result
                        withMethodType:aChannelName
                             withError:error
                            withParams:data];
                  }];
}

- (void)fetchMembersAttributes:(NSDictionary *)param
                withMethodType:(NSString *)aChannelName
                        result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;

    NSString *groupId = param[@"groupId"];
    NSArray<NSString *> *userIds = param[@"members"];
    NSArray<NSString *> *keys = param[@"keys"];
    [AgoraChatClient.sharedClient.groupManager
        fetchMembersAttributes:groupId
                       userIds:userIds
                          keys:keys
                    completion:^(
                        NSDictionary<NSString *,
                                     NSDictionary<NSString *, NSString *> *>
                            *_Nullable attributes,
                        AgoraChatError *_Nullable error) {
                      [weakSelf onResult:result
                          withMethodType:aChannelName
                               withError:error
                              withParams:attributes];
                    }];
}

- (void)fetchJoinedGroupCount:(NSDictionary *)param
               withMethodType:(NSString *)aChannelName
                       result:(nonnull id<ExtSdkCallbackObjc>)result {
    __weak typeof(self) weakSelf = self;
    [AgoraChatClient.sharedClient.groupManager
        getJoinedGroupsCountFromServerWithCompletion:^(
            NSInteger groupCount, AgoraChatError *_Nullable aError) {
          [weakSelf onResult:result
              withMethodType:aChannelName
                   withError:aError
                  withParams:@(groupCount)];
        }];
}

#pragma mark - AgoraChatGroupManagerDelegate

- (void)groupInvitationDidReceive:(NSString *_Nonnull)aGroupId
                        groupName:(NSString *_Nonnull)aGroupName
                          inviter:(NSString *_Nonnull)aInviter
                          message:(NSString *_Nullable)aMessage {
    NSDictionary *map = @{
        @"type" : @"onInvitationReceived",
        @"groupId" : aGroupId,
        @"groupName" : aGroupName,
        @"inviter" : aInviter,
        @"message" : aMessage
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupInvitationDidAccept:(AgoraChatGroup *)aGroup
                         invitee:(NSString *)aInvitee {
    NSDictionary *map = @{
        @"type" : @"onInvitationAccepted",
        @"groupId" : aGroup.groupId,
        @"invitee" : aInvitee
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupInvitationDidDecline:(AgoraChatGroup *)aGroup
                          invitee:(NSString *)aInvitee
                           reason:(NSString *)aReason {
    NSDictionary *map = @{
        @"type" : @"onInvitationDeclined",
        @"groupId" : aGroup.groupId,
        @"invitee" : aInvitee,
        @"reason" : aReason
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)didJoinGroup:(AgoraChatGroup *)aGroup
             inviter:(NSString *)aInviter
             message:(NSString *)aMessage {
    NSDictionary *map = @{
        @"type" : @"onAutoAcceptInvitationFromGroup",
        @"groupId" : aGroup.groupId,
        @"message" : aMessage,
        @"inviter" : aInviter
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)didLeaveGroup:(AgoraChatGroup *)aGroup reason:(AgoraChatGroupLeaveReason)aReason {
    NSString *type;
    if (aReason == AgoraChatGroupLeaveReasonBeRemoved) {
        type = @"onUserRemoved";
    } else if (aReason == AgoraChatGroupLeaveReasonDestroyed) {
        type = @"onGroupDestroyed";
    }
    NSDictionary *map = @{
        @"type" : type,
        @"groupId" : aGroup.groupId,
        @"groupName" : aGroup.groupName
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)joinGroupRequestDidReceive:(AgoraChatGroup *)aGroup
                              user:(NSString *)aUsername
                            reason:(NSString *)aReason {
    NSDictionary *map = @{
        @"type" : @"onRequestToJoinReceived",
        @"groupId" : aGroup.groupId,
        @"applicant" : aUsername,
        @"reason" : aReason
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)joinGroupRequestDidDecline:(NSString *)aGroupId
                            reason:(NSString *)aReason {
    //    NSDictionary *map = @{
    //        @"type" : @"onRequestToJoinDeclined",
    //        @"groupId" : aGroupId,
    //        @"reason" : aReason
    //    };
    //    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)joinGroupRequestDidDecline:(NSString *_Nonnull)aGroupId
                            reason:(NSString *_Nullable)aReason
                          decliner:(NSString *_Nullable)aDecliner
                         applicant:(NSString *_Nonnull)aApplicant {
    NSDictionary *map = @{
        @"type" : @"onRequestToJoinDeclined",
        @"groupId" : aGroupId,
        @"applicant" : aApplicant,
        @"reason" : aReason
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)joinGroupRequestDidApprove:(AgoraChatGroup *)aGroup {
    NSDictionary *map = @{
        @"type" : @"onRequestToJoinAccepted",
        @"groupId" : aGroup.groupId,
        @"groupName" : aGroup.groupName,
        @"accepter" : aGroup.owner,
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupMuteListDidUpdate:(AgoraChatGroup *)aGroup
             addedMutedMembers:(NSArray *)aMutedMembers
                    muteExpire:(NSInteger)aMuteExpire {
    NSDictionary *map = @{
        @"type" : @"onMuteListAdded",
        @"groupId" : aGroup.groupId,
        @"mutes" : aMutedMembers,
        @"muteExpire" : [NSNumber numberWithInteger:aMuteExpire]
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupMuteListDidUpdate:(AgoraChatGroup *)aGroup
           removedMutedMembers:(NSArray *)aMutedMembers {
    NSDictionary *map = @{
        @"type" : @"onMuteListRemoved",
        @"groupId" : aGroup.groupId,
        @"mutes" : aMutedMembers
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupWhiteListDidUpdate:(AgoraChatGroup *)aGroup
          addedWhiteListMembers:(NSArray *)aMembers {
    NSDictionary *map = @{
        @"type" : @"onAllowListAdded",
        @"groupId" : aGroup.groupId,
        @"members" : aMembers
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupWhiteListDidUpdate:(AgoraChatGroup *)aGroup
        removedWhiteListMembers:(NSArray *)aMembers {
    NSDictionary *map = @{
        @"type" : @"onAllowListRemoved",
        @"groupId" : aGroup.groupId,
        @"members" : aMembers
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupAllMemberMuteChanged:(AgoraChatGroup *)aGroup
                 isAllMemberMuted:(BOOL)aMuted {
    NSDictionary *map = @{
        @"type" : @"onAllMemberMuteStateChanged",
        @"groupId" : aGroup.groupId,
        @"isMuted" : @(aMuted)
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupAdminListDidUpdate:(AgoraChatGroup *)aGroup
                     addedAdmin:(NSString *)aAdmin {
    NSDictionary *map = @{
        @"type" : @"onAdminAdded",
        @"groupId" : aGroup.groupId,
        @"administrator" : aAdmin
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupAdminListDidUpdate:(AgoraChatGroup *)aGroup
                   removedAdmin:(NSString *)aAdmin {
    NSDictionary *map = @{
        @"type" : @"onAdminRemoved",
        @"groupId" : aGroup.groupId,
        @"administrator" : aAdmin
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupOwnerDidUpdate:(AgoraChatGroup *)aGroup
                   newOwner:(NSString *)aNewOwner
                   oldOwner:(NSString *)aOldOwner {
    NSDictionary *map = @{
        @"type" : @"onOwnerChanged",
        @"groupId" : aGroup.groupId,
        @"newOwner" : aNewOwner,
        @"oldOwner" : aOldOwner
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)userDidJoinGroup:(AgoraChatGroup *)aGroup user:(NSString *)aUsername {
    NSDictionary *map = @{
        @"type" : @"onMemberJoined",
        @"groupId" : aGroup.groupId,
        @"member" : aUsername
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)userDidLeaveGroup:(AgoraChatGroup *)aGroup user:(NSString *)aUsername {
    NSDictionary *map = @{
        @"type" : @"onMemberExited",
        @"groupId" : aGroup.groupId,
        @"member" : aUsername
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupAnnouncementDidUpdate:(AgoraChatGroup *)aGroup
                      announcement:(NSString *)aAnnouncement {
    NSDictionary *map = @{
        @"type" : @"onAnnouncementChanged",
        @"groupId" : aGroup.groupId,
        @"announcement" : aAnnouncement
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupFileListDidUpdate:(AgoraChatGroup *)aGroup
               addedSharedFile:(AgoraChatGroupSharedFile *)aSharedFile {
    NSDictionary *map = @{
        @"type" : @"onSharedFileAdded",
        @"groupId" : aGroup.groupId,
        @"sharedFile" : [aSharedFile toJsonObject]
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupFileListDidUpdate:(AgoraChatGroup *)aGroup
             removedSharedFile:(NSString *)aFileId {
    NSDictionary *map = @{
        @"type" : @"onSharedFileDeleted",
        @"groupId" : aGroup.groupId,
        @"fileId" : aFileId
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupSpecificationDidUpdate:(AgoraChatGroup *)aGroup {
    NSDictionary *map = @{
        @"type" : @"onSpecificationChanged",
        @"group" : [aGroup toJsonObject],
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)groupStateChanged:(AgoraChatGroup *)aGroup isDisabled:(BOOL)aDisabled {
    NSDictionary *map = @{
        @"type" : @"onStateChanged",
        @"group" : [aGroup toJsonObject],
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

- (void)onAttributesChangedOfGroupMember:(NSString *_Nonnull)groupId
                                  userId:(NSString *_Nonnull)userId
                              attributes:(NSDictionary<NSString *, NSString *>
                                              *_Nullable)attributes
                              operatorId:(NSString *_Nonnull)operatorId {
    NSDictionary *map = @{
        @"type" : @"onMemberAttributesChanged",
        @"groupId" : groupId,
        @"member" : userId,
        @"attributes" : attributes,
        @"operator" : operatorId,
    };
    [self onReceive:ExtSdkMethodKeyOnGroupChanged withParams:map];
}

@end
