




#import "ACPluginJSBridge.h"
#import "ACBaseJSPlugin.h"
#import "ACBridgeUtil.h"
#import "ACMessage.h"
#import "ACBaseJSConstant.h"
#import "ACBaseJSPlugin.h"

@interface ACPluginJSBridge ()

@property (nonatomic, strong) NSMutableArray<ACBaseJSPlugin *> *plugsAr;

@end

@implementation ACPluginJSBridge

/**
 Js调用native方法

 @param plugNameStr 插件名称
 @param functionStr native方法名
 @param msgStr 属性json
 */
- (void)execPlugWithPlugName:(NSString *)plugNameStr Function:(NSString *)functionStr Message:(NSString *)msgStr
{
    if (plugNameStr == nil) {
        return;
    }
    // 从插件列表中找到该插件
    NSMutableArray<ACBaseJSPlugin *> *plugsAr = [self plugsAr];
    __block ACBaseJSPlugin *plug = nil;
    [plugsAr enumerateObjectsUsingBlock:^(ACBaseJSPlugin * tempPlug, NSUInteger idx, BOOL *stop) {
        if ([tempPlug.nameStr isEqualToString:plugNameStr]) {
            plug = tempPlug;
            *stop = YES;
        }
    }];

    // 从配置文件创建插件并执行插件方法
    void (^createAndExecPlugBlock)(void) = ^() {
        ACBaseJSPlugin *baseJSPlugin = [self createJSPluginWithPlugName:plugNameStr];
        if (baseJSPlugin != nil) {
            // 配置文件找到并创建该插件，将该插件加入插件列表
            [plugsAr addObject:baseJSPlugin];
            // 执行该插件的native方法
            [self callFunctionWithObj:baseJSPlugin functionName:functionStr message:[ACBridgeUtil convertStringToMessage:msgStr]];
        }
    };
    
    if (plug == nil) {
        // 未找到该插件，从config创建该插件
            createAndExecPlugBlock();
    }
    else {
        // 找到该插件
        if (plug.webView != nil && plug.vc != nil) {
            // 执行该插件的native方法
            [self callFunctionWithObj:plug functionName:functionStr message:[ACBridgeUtil convertStringToMessage:msgStr]];
        }
        else {
            // 若插件不可用，则移除该插件并重新创建它
            [plugsAr removeObject:plug];
            
            createAndExecPlugBlock();
        }
    }
}

/**
 创建插件
 
 @param plugNameStr 插件名称
 */
- (ACBaseJSPlugin *)createJSPluginWithPlugName:(NSString *)plugNameStr
{
    // 读取插件config并创建该插件
//    Class plugClass = [[ACAbilityConfig sharedInstance] classOfPlugName:plugNameStr];
    Class plugClass = NSClassFromString(plugNameStr);
    if (plugClass == nil) {
        return nil;
    }
    ACBaseJSPlugin *baseJSPlugin = nil;
    if (plugClass != nil) {
        baseJSPlugin = [[plugClass alloc] init];
        baseJSPlugin.nameStr = plugNameStr;
        baseJSPlugin.nativeCalled = NO;
        baseJSPlugin.webView = self.webView;
        baseJSPlugin.vc = self.vc;
    }
    return baseJSPlugin;
}

/**
 调用native方法

 @param obj 调用对象
 @param functionNameStr 方法名称
 */
- (void)callFunctionWithObj:(id)obj functionName:(NSString *)functionNameStr message:(ACMessage *)msg
{
    NSString *ocFunctionNameStr = [NSString stringWithFormat:@"%@:",functionNameStr];
    
    if ([obj respondsToSelector:NSSelectorFromString(ocFunctionNameStr)]) {
        if (![NSThread isMainThread]) {
            dispatch_sync(dispatch_get_main_queue(), ^{
                [obj performSelector:NSSelectorFromString(ocFunctionNameStr) withObject:msg];
            });
        }
        else {
            [obj performSelector:NSSelectorFromString(ocFunctionNameStr) withObject:msg];
        }
    }
}

#pragma mark - getter and setter

- (NSMutableArray<ACBaseJSPlugin *> *)plugsAr
{
    if (_plugsAr == nil) {
        _plugsAr = [NSMutableArray new];
    }
    return _plugsAr;
}

@end
