//
//  Router.m
//  RNArenaKit
//
//  Created by 陈云杰 on 2017/11/6.
//  Copyright © 2017年 Facebook. All rights reserved.
//

#import "Router.h"
#import "UIViewController+Controller.h"
#import "App.h"
#import "ArenaRuntime.h"
#import "WKWebViewController.h"
#import "ReactNativeViewController.h"

static Router *router = nil;

//成功回调映射
static NSMutableDictionary *successResolverMap = nil;

//失败回调映射
static NSMutableDictionary *failResolverMap = nil;

static NSMutableArray *closeViewControllerCallback = nil;

static NSMutableDictionary *sessionMap = nil;
@implementation Router

+ (Router *) defaultRouter {
    if (router == nil) {
        router = [Router new];
        sessionMap = [NSMutableDictionary new];
        successResolverMap = [NSMutableDictionary new];
        failResolverMap = [NSMutableDictionary new];
        closeViewControllerCallback = [NSMutableArray new];
    }
    return router;
}


- (void) dispatchWithMessage:(Message *) message onSuccess:(void (^)(id)) success onFailed: (void (^)(id)) failed {
    NSDictionary *parameters = message.parameters;
    if (parameters != nil) {
        //取调用方法
        NSString *apiName = [parameters objectForKey:@"method"];
        //取调用所需参数
        NSDictionary *messageParameters = [parameters objectForKey:@"params"];
        
        switch (message.type) {
            case MessageTypeApi:
                //api调用
                [self dispatchApisWithApiName:apiName withParameters: messageParameters onSuccess:success onFailed:failed];
                break;
            case MessageTypeClose:
                [[[UIViewController current] navigationController] popViewControllerAnimated:YES];
                break;
            case MessageTypeSetResult:
                [self dispatchSetResultWithParameters:parameters];
                break;
            case MessageTypeSessionGet:
                [self dispatchSessionGetWithKey:[parameters objectForKey:@"key"]  onSuccess:success onFailed:failed];
                break;
            case MessageTypeSessionSet:
                [self dispatchSessionSetWithValue:[parameters valueForKey:@"key"] forKey:[parameters valueForKey:@"value"] onSuccess:success onFailed:failed];
                break;
            case MessageTypeRedirect:{
                NSDictionary *redirecParameters = [parameters objectForKey:@"params"];
                NSString *key = [redirecParameters valueForKey:@"key"];
                
                if (key != nil && (NSNull *) key != [NSNull null]) {
                    
                    App *app = [[ArenaRuntime defaultRuntime] appOfKey:key];
                    if (app != nil && (NSNull *) app != [NSNull null]) {
                        [self dispathcViewControllerWithApp:app withParameters:[parameters valueForKey:@"value"] onSuccess:success onFailed:failed];
                    }
                }
            }
            break;
            case MessageTypeLogout:
            default:
            break;
        }
    }
}

//设置session临时存储
- (void) dispatchSessionSetWithValue:(id) value forKey: (NSString *) key onSuccess:(void (^)(id)) success onFailed: (void (^)(id)) failed {
    if (key == nil || (NSNull *)key == [NSNull null] || value == nil || (NSNull *)key == [NSNull null]) {
        failed(@"key或value不能为空");
    } else {
        [sessionMap setObject:value forKey:key];
    }
}

//session取值
- (void) dispatchSessionGetWithKey: (NSString *) key onSuccess:(void (^)(id)) success onFailed: (void (^)(id)) failed {
    if (key == nil || (NSNull *)key == [NSNull null]) {
        failed(@"key不能为空");
    } else {
        id value = [sessionMap objectForKey:key];
        
        if (value == nil) {
            success([NSNull null]);
        } else {
            success(value);
        }
    }
}

//set result 往回写值
- (void) dispatchSetResultWithParameters:(NSDictionary *) parameters {
    
    if (closeViewControllerCallback != nil && closeViewControllerCallback.count > 0) {
        ((void (^)(id))closeViewControllerCallback.lastObject)(parameters);
        [closeViewControllerCallback removeLastObject];
        [[[UIViewController current] navigationController] popViewControllerAnimated:YES];
    }
    
}

//分发页面跳转
- (void) dispathcViewControllerWithApp: (App *) app withParameters: (NSDictionary *) parameters onSuccess:(void (^)(id)) success onFailed: (void (^)(id)) failed {
    
    if (closeViewControllerCallback == nil) {
        closeViewControllerCallback = [NSMutableArray new];
    }
    
    if (app != nil) {
        [closeViewControllerCallback addObject:success];
        
        UINavigationController *navigationController = [[UIViewController current] navigationController];
        
        
        if (app.type == 1) {
            //html类型微应用
            
            WKWebViewController *webviewController = [[WKWebViewController alloc] initWithApp:app andParameters:parameters];
            webviewController.hidesBottomBarWhenPushed = YES;
            [navigationController pushViewController:webviewController animated:YES];
            
        } else if (app.type == 2) {
            //react native 类型微应用
            
            ReactNativeViewController *reactNativeViewController = [[ReactNativeViewController alloc] initWithApp:app andParameters:parameters];
            reactNativeViewController.hidesBottomBarWhenPushed = YES;
            [navigationController pushViewController:reactNativeViewController animated:YES];
        }
    }
    
    
}
//分发api调用
-(void) dispatchApisWithApiName: (NSString *) apiName withParameters: (NSDictionary *) parameters onSuccess:(void (^)(id)) success onFailed: (void (^)(id)) failed {
    NSDictionary *api = [[ArenaRuntime defaultRuntime] apiOfApiName:apiName];
    
    if (api == nil) {
        return;
    }
    
    NSString *className = [api objectForKey:@"className"];
    NSString *method = [api objectForKey:@"method"];
    NSString *namespace = [api objectForKey:@"namespace"];
    bool async = [[api objectForKey:@"async"] isEqualToString:@"YES"];
    
    NSString *fullClassName = @"";
    
    if (namespace != nil) {
        fullClassName = [NSString stringWithFormat:@"%@.%@", namespace, className];
    } else {
        fullClassName = className;
    }
    
    Class ObjectClass = NSClassFromString(fullClassName);
    
    if (ObjectClass != nil && method != nil) {
        SEL methodSelector = NSSelectorFromString(method);
        if (async == YES) {
            NSString *callbackId = [NSString stringWithFormat:@"callback_%@", [self createUUID]];
            
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(callbackFromPlugins:) name:callbackId object:nil];
            [successResolverMap setObject:success forKey:callbackId];
            [failResolverMap setObject:failed forKey:callbackId];
            
            if (parameters != nil) {
                NSMutableDictionary *params = [[NSMutableDictionary alloc] initWithDictionary:parameters];
                [params setObject:callbackId forKey:@"callback"];
                if (methodSelector != nil && [ObjectClass respondsToSelector: methodSelector]) {
                
                    [ObjectClass performSelector:methodSelector withObject:params];
                }
            } else {
                if (methodSelector != nil && [ObjectClass respondsToSelector: methodSelector]) {
                    
                    [ObjectClass performSelector:methodSelector withObject: [[NSDictionary alloc] initWithObjectsAndKeys:callbackId, @"callback", nil]];
                }
            }
        } else {
            id value = (NSString *)[ObjectClass performSelector:methodSelector withObject:parameters];
            
            if (value != nil) {
                success(value);
            } else {
                failed(@"失败");
            }
        }
    }
}


////api回调
- (void) callbackFromPlugins: (NSNotification *) notification {
    NSDictionary *result = [notification object];
    
    if (result != nil) {
        NSString *resultCode = [result valueForKey:@"result"];
        if (resultCode != nil && [resultCode isEqualToString:@"success"]) {
            if (successResolverMap[notification.name]) {
                ((void(^)(id))successResolverMap[notification.name])([result objectForKey:@"data"]);
            }
        } else {
            if (failResolverMap[notification.name]) {
                ((void(^)(id))failResolverMap[notification.name])(@"失败");
            }
        }
        
        //清理回调
        [failResolverMap removeObjectForKey:notification.name];
        [successResolverMap removeObjectForKey:notification.name];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:notification.name object:nil];
    }
}

- (NSString *)createUUID
{
    CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
    return (NSString *)CFBridgingRelease(CFUUIDCreateString (kCFAllocatorDefault,uuidRef));
}

@end
