//
//  NSObject+Common.m
//  Coding_iOS
//
//  Created by 王 原闯 on 14-7-31.
//  Copyright (c) 2014年 Coding. All rights reserved.
//
#define kPath_ImageCache @"ImageCache"
#define kPath_ResponseCache @"ResponseCache"
#define kHUDQueryViewTag 101

#define kBaseURLStr @"https://coding.net/"
#define kBaseCompanySuffixStr @"coding.net"
#define kBaseCompanyKey @"k_base_company"

#define kIsPrivateCloudKey @"k_is_private_cloud"
#define kPrivateCloudKey @"k_private_cloud"

#import "NSObject+Common.h"
#import "JDStatusBarNotification.h"
#import "Login.h"
#import "AppDelegate.h"
#import "CodingNetAPIClient.h"
#import "Coding_NetAPIManager.h"

@implementation NSObject (Common)

#pragma mark Tip M
+ (NSString *)tipFromError:(NSError *)error{
    if (error && error.userInfo) {
        NSMutableString *tipStr = [[NSMutableString alloc] init];
        if ([error.userInfo objectForKey:@"msg"]) {
            NSArray *msgArray = [[error.userInfo objectForKey:@"msg"] allValues];
            NSUInteger num = [msgArray count];
            for (int i = 0; i < num; i++) {
                NSString *msgStr = [msgArray objectAtIndex:i];
                HtmlMedia *media = [HtmlMedia htmlMediaWithString:msgStr showType:MediaShowTypeAll];
                msgStr = media.contentDisplay;
                if (i+1 < num) {
                    [tipStr appendString:[NSString stringWithFormat:@"%@\n", msgStr]];
                }else{
                    [tipStr appendString:msgStr];
                }
            }
        }else{
            if (error.userInfo[NSUnderlyingErrorKey]) {
                tipStr = [self tipFromError:error.userInfo[NSUnderlyingErrorKey]].mutableCopy;
            }else if (error.userInfo[NSLocalizedDescriptionKey]) {
                tipStr = error.userInfo[NSLocalizedDescriptionKey];
            }else{
                if (error.code == 3840) {//Json 解析失败
                    [tipStr appendFormat:@"服务器返回数据格式有误"];
                }else{
                    [tipStr appendFormat:@"错误代码 %ld", (long)error.code];
                }
            }
        }
        return tipStr;
    }
    return nil;
}
+ (BOOL)showError:(NSError *)error{
    if ([JDStatusBarNotification isVisible]) {//如果statusBar上面正在显示信息，则不再用hud显示error
        NSLog(@"如果statusBar上面正在显示信息，则不再用hud显示error");
        return NO;
    }
    NSString *tipStr = [NSObject tipFromError:error];
    [NSObject showHudTipStr:tipStr];
    return YES;
}
+ (void)showHudTipStr:(NSString *)tipStr{
    if (tipStr && tipStr.length > 0) {
        MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:kKeyWindow animated:YES];
        hud.mode = MBProgressHUDModeText;
        hud.detailsLabelFont = [UIFont boldSystemFontOfSize:15.0];
        hud.detailsLabelText = tipStr;
        hud.margin = 10.f;
        hud.removeFromSuperViewOnHide = YES;
        [hud hide:YES afterDelay:1.0];
    }
}
+ (MBProgressHUD *)showHUDQueryStr:(NSString *)titleStr{
    titleStr = titleStr.length > 0? titleStr: @"正在获取数据...";
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:kKeyWindow animated:YES];
    hud.tag = kHUDQueryViewTag;
    hud.labelText = titleStr;
    hud.labelFont = [UIFont boldSystemFontOfSize:15.0];
    hud.margin = 10.f;
    return hud;
}
+ (NSUInteger)hideHUDQuery{
    __block NSUInteger count = 0;
    NSArray *huds = [MBProgressHUD allHUDsForView:kKeyWindow];
    [huds enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
        if (obj.tag == kHUDQueryViewTag) {
            [obj removeFromSuperview];
            count++;
        }
    }];
    return count;
}
+ (void)showStatusBarQueryStr:(NSString *)tipStr{
    [JDStatusBarNotification showWithStatus:tipStr styleName:JDStatusBarStyleSuccess];
    [JDStatusBarNotification showActivityIndicator:YES indicatorStyle:UIActivityIndicatorViewStyleWhite];
}
+ (void)showStatusBarSuccessStr:(NSString *)tipStr{
    if ([JDStatusBarNotification isVisible]) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [JDStatusBarNotification showActivityIndicator:NO indicatorStyle:UIActivityIndicatorViewStyleWhite];
            [JDStatusBarNotification showWithStatus:tipStr dismissAfter:1.5 styleName:JDStatusBarStyleSuccess];
        });
    }else{
        [JDStatusBarNotification showActivityIndicator:NO indicatorStyle:UIActivityIndicatorViewStyleWhite];
        [JDStatusBarNotification showWithStatus:tipStr dismissAfter:1.0 styleName:JDStatusBarStyleSuccess];
    }
}
+ (void)showStatusBarErrorStr:(NSString *)errorStr{
    if ([JDStatusBarNotification isVisible]) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [JDStatusBarNotification showActivityIndicator:NO indicatorStyle:UIActivityIndicatorViewStyleWhite];
            [JDStatusBarNotification showWithStatus:errorStr dismissAfter:1.5 styleName:JDStatusBarStyleError];
        });
    }else{
        [JDStatusBarNotification showActivityIndicator:NO indicatorStyle:UIActivityIndicatorViewStyleWhite];
        [JDStatusBarNotification showWithStatus:errorStr dismissAfter:1.5 styleName:JDStatusBarStyleError];
    }
}

+ (void)showStatusBarError:(NSError *)error{
    NSString *errorStr = [NSObject tipFromError:error];
    [NSObject showStatusBarErrorStr:errorStr];
}

#pragma mark BaseURL
+ (NSString *)baseURLStr{
    if (kTarget_Enterprise) {
        if ([self isPrivateCloud].boolValue) {
            return [self privateCloud];
        }else{
            if (![self baseCompany]) {
                return nil;
            }
            NSString *baseURLStr = [NSString stringWithFormat:@"%@://%@.%@/", ([self baseURLStrIsProduction]? @"https": @"http"), [self baseCompany], [self baseCompanySuffixStr]];
            return baseURLStr;
        }
    }else{
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        return [defaults valueForKey:kBaseURLStr] ?: kBaseURLStr;
    }
}

+ (BOOL)baseURLStrIsProduction{
    if (kTarget_Enterprise) {
        return [[self baseCompanySuffixStr] isEqualToString:kBaseCompanySuffixStr];
    }else{
        return [[self baseURLStr] isEqualToString:kBaseURLStr];
    }
}

+ (void)changeBaseURLStrTo:(NSString *)baseURLStr{
    if (baseURLStr.length <= 0) {
        baseURLStr = kBaseURLStr;
    }else if (![baseURLStr hasSuffix:@"/"]){
        baseURLStr = [baseURLStr stringByAppendingString:@"/"];
    }

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:baseURLStr forKey:kBaseURLStr];
    [defaults synchronize];
    
    [CodingNetAPIClient changeJsonClient];
    
    [[UINavigationBar appearance] setBackgroundImage:[UIImage imageWithColor:[self baseURLStrIsProduction]? kColorNavBG: kColorActionYellow] forBarMetrics:UIBarMetricsDefault];
}

+ (NSString *)e_URLStr{
    NSString *baseURLStr = [NSString stringWithFormat:@"%@://e.%@/", ([self baseURLStrIsProduction]? @"https": @"http"), [self baseCompanySuffixStr]];
    return [self isPrivateCloud].boolValue? [self privateCloud]: baseURLStr;
}

+ (NSString *)baseCompanySuffixStr{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *baseCompanySuffixStr = [defaults valueForKey:kBaseCompanySuffixStr] ?: kBaseCompanySuffixStr;
    return [baseCompanySuffixStr lowercaseString];
}
+ (void)changeBaseCompanySuffixStrTo:(NSString *)companySuffixStr{
    if (companySuffixStr.length <= 0) {
        companySuffixStr = kBaseCompanySuffixStr;
    }
    if (![companySuffixStr isEqualToString:[self baseCompanySuffixStr]]) {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:companySuffixStr forKey:kBaseCompanySuffixStr];
        [defaults synchronize];
        
        [[UINavigationBar appearance] setBackgroundImage:[UIImage imageWithColor:[self baseURLStrIsProduction]? kColorNavBG: kColorBrandBlue] forBarMetrics:UIBarMetricsDefault];
        
        if ([self baseCompany]) {
            [CodingNetAPIClient changeSharedJsonClient];
        }
        [CodingNetAPIClient changeE_JsonClient];
    }
}

+ (NSString *)baseCompany{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *baseCompany = [defaults valueForKey:kBaseCompanyKey];
    return [self isPrivateCloud].boolValue? @"ce": baseCompany;
}
+ (void)changeBaseCompanyTo:(NSString *)company{
    if ([self isPrivateCloud].boolValue) {
        [self changePrivateCloudTo:company];
    }else if (![company isEqualToString:[self baseCompany]]) {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:company ?: @"" forKey:kBaseCompanyKey];
        [defaults synchronize];
        
        [CodingNetAPIClient changeSharedJsonClient];
    }
}

+ (NSNumber *)isPrivateCloud{
    //    return @(YES);
    return [[NSUserDefaults standardUserDefaults] valueForKey:kIsPrivateCloudKey];
}
+ (void)setupIsPrivateCloud:(NSNumber *)isPrivateCloud{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if (isPrivateCloud) {
        [defaults setObject:isPrivateCloud forKey:kIsPrivateCloudKey];
    }else{
        [defaults removeObjectForKey:kIsPrivateCloudKey];
    }
    [defaults synchronize];
    [CodingNetAPIClient changeSharedJsonClient];
}
+ (NSString *)privateCloud{
    //    return @"http://pd.codingprod.net/";
    return [[NSUserDefaults standardUserDefaults] valueForKey:kPrivateCloudKey];
}
+ (void)changePrivateCloudTo:(NSString *)privateCloud{
    if (privateCloud.length > 0) {
        if (![privateCloud hasPrefix:@"http"]) {
            privateCloud = [NSString stringWithFormat:@"http://%@", privateCloud];
        }
        if (![privateCloud hasSuffix:@"/"]) {
            privateCloud = [privateCloud stringByAppendingString:@"/"];
        }
    }
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:privateCloud ?: @"" forKey:kPrivateCloudKey];
    [defaults synchronize];
    
    [CodingNetAPIClient changeSharedJsonClient];
}

#pragma mark File M
//获取fileName的完整地址
+ (NSString* )pathInCacheDirectory:(NSString *)fileName
{
    NSArray *cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [cachePaths objectAtIndex:0];
    return [cachePath stringByAppendingPathComponent:fileName];
}
//创建缓存文件夹
+ (BOOL) createDirInCache:(NSString *)dirName
{
    NSString *dirPath = [self pathInCacheDirectory:dirName];
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:dirPath isDirectory:&isDir];
    BOOL isCreated = NO;
    if ( !(isDir == YES && existed == YES) )
    {
        isCreated = [fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    if (existed) {
        isCreated = YES;
    }
    return isCreated;
}



// 图片缓存到本地
+ (BOOL) saveImage:(UIImage *)image imageName:(NSString *)imageName inFolder:(NSString *)folderName
{
    if (!image) {
        return NO;
    }
    if (!folderName) {
        folderName = kPath_ImageCache;
    }
    if ([self createDirInCache:folderName]) {
        NSString * directoryPath = [self pathInCacheDirectory:folderName];
        BOOL isDir = NO;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL existed = [fileManager fileExistsAtPath:directoryPath isDirectory:&isDir];
        bool isSaved = false;
        if ( isDir == YES && existed == YES )
        {
            isSaved = [[image dataForCodingUpload] writeToFile:[directoryPath stringByAppendingPathComponent:imageName] options:NSAtomicWrite error:nil];
        }
        return isSaved;
    }else{
        return NO;
    }
}
// 获取缓存图片
+ (NSData*) loadImageDataWithName:( NSString *)imageName inFolder:(NSString *)folderName
{
    if (!folderName) {
        folderName = kPath_ImageCache;
    }
    NSString * directoryPath = [self pathInCacheDirectory:folderName];
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL dirExisted = [fileManager fileExistsAtPath:directoryPath isDirectory:&isDir];
    if ( isDir == YES && dirExisted == YES )
    {
        NSString *abslutePath = [NSString stringWithFormat:@"%@/%@", directoryPath, imageName];
        BOOL fileExisted = [fileManager fileExistsAtPath:abslutePath];
        if (!fileExisted) {
            return NULL;
        }
        NSData *imageData = [NSData dataWithContentsOfFile : abslutePath];
        return imageData;
    }
    else
    {
        return NULL;
    }
}

// 删除图片缓存
+ (BOOL) deleteImageCacheInFolder:(NSString *)folderName{
    if (!folderName) {
        folderName = kPath_ImageCache;
    }
    return [self deleteCacheWithPath:folderName];
}


//网络请求
+ (BOOL)saveResponseData:(NSDictionary *)data toPath:(NSString *)requestPath{
    User *loginUser = [Login curLoginUser];
    if (!loginUser) {
        return NO;
    }else{
        requestPath = [NSString stringWithFormat:@"%@_%@", loginUser.global_key, requestPath];
    }
    if ([self createDirInCache:kPath_ResponseCache]) {
        NSString *abslutePath = [NSString stringWithFormat:@"%@/%@.plist", [self pathInCacheDirectory:kPath_ResponseCache], [requestPath md5Str]];
        return [data writeToFile:abslutePath atomically:YES];
    }else{
        return NO;
    }
}
+ (id) loadResponseWithPath:(NSString *)requestPath{//返回一个NSDictionary类型的json数据
    User *loginUser = [Login curLoginUser];
    if (!loginUser) {
        return nil;
    }else{
        requestPath = [NSString stringWithFormat:@"%@_%@", loginUser.global_key, requestPath];
    }
    NSString *abslutePath = [NSString stringWithFormat:@"%@/%@.plist", [self pathInCacheDirectory:kPath_ResponseCache], [requestPath md5Str]];
    return [NSMutableDictionary dictionaryWithContentsOfFile:abslutePath];
}

+ (BOOL)deleteResponseCacheForPath:(NSString *)requestPath{
    User *loginUser = [Login curLoginUser];
    if (!loginUser) {
        return NO;
    }else{
        requestPath = [NSString stringWithFormat:@"%@_%@", loginUser.global_key, requestPath];
    }
    NSString *abslutePath = [NSString stringWithFormat:@"%@/%@.plist", [self pathInCacheDirectory:kPath_ResponseCache], [requestPath md5Str]];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:abslutePath]) {
        return [fileManager removeItemAtPath:abslutePath error:nil];
    }else{
        return NO;
    }
}

+ (BOOL) deleteResponseCache{
    return [self deleteCacheWithPath:kPath_ResponseCache];
}

+ (NSUInteger)getResponseCacheSize {
    NSString *dirPath = [self pathInCacheDirectory:kPath_ResponseCache];
    NSUInteger size = 0;
    NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:dirPath];
    for (NSString *fileName in fileEnumerator) {
        NSString *filePath = [dirPath stringByAppendingPathComponent:fileName];
        NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
        size += [attrs fileSize];
    }
    return size;
}


+ (BOOL) deleteCacheWithPath:(NSString *)cachePath{
    NSString *dirPath = [self pathInCacheDirectory:cachePath];
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:dirPath isDirectory:&isDir];
    bool isDeleted = false;
    if ( isDir == YES && existed == YES )
    {
        isDeleted = [fileManager removeItemAtPath:dirPath error:nil];
    }
    return isDeleted;
}

#pragma mark NetError
-(id)handleResponse:(id)responseJSON{
    return [self handleResponse:responseJSON autoShowError:YES];
}
-(id)handleResponse:(id)responseJSON autoShowError:(BOOL)autoShowError{
    NSError *error = nil;
    //code为非0值时，表示有错
    NSInteger errorCode = [(NSNumber *)[responseJSON valueForKeyPath:@"code"] integerValue];
    
    if (errorCode != 0) {
        error = [NSError errorWithDomain:[NSObject baseURLStr] code:errorCode userInfo:responseJSON];
        if (errorCode == 1000 || errorCode == 3207) {//用户未登录
            if ([Login isLogin]) {
                [Login doLogout];//已登录的状态要抹掉
                //更新 UI 要延迟 >1.0 秒，否则屏幕可能会不响应触摸事件。。暂不知为何
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [((AppDelegate *)[UIApplication sharedApplication].delegate) setupLoginViewController];
                    kTipAlert(@"%@", [NSObject tipFromError:error]);
                });
            }
        }else{
            //验证码弹窗
            NSMutableDictionary *params = nil;
            if (errorCode == 907) {//operation_need_captcha 比如：每日新增关注用户超过 20 个
                params = @{@"type": @3}.mutableCopy;
            }else if (errorCode == 1018){//user_not_get_request_too_many
                params = @{@"type": @1}.mutableCopy;
            }
            if (params) {
                [NSObject showCaptchaViewParams:params];
            }
            //错误提示
            if (autoShowError) {
                [NSObject showError:error];
            }
        }
    }
    return error;
}

+ (void)showCaptchaViewParams:(NSMutableDictionary *)params{
    [self showCaptchaViewParams:params success:nil];
}

+ (void)showCaptchaViewParams:(NSMutableDictionary *)params success:(void (^)())block{
    //Data
    if (!params) {
        params = @{}.mutableCopy;
    }
    if (!params[@"type"]) {
        params[@"type"] = @1;
    }
    NSString *path = @"api/request_valid";
    NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@api/getCaptcha?type=%@", [NSObject baseURLStr], params[@"type"]]];
    //UI
    SDCAlertController *alertV = [SDCAlertController alertControllerWithTitle:@"提示" message:@"请输入图片验证码" preferredStyle:SDCAlertControllerStyleAlert];
    UITextField *textF = [UITextField new];
    textF.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0);
    textF.backgroundColor = [UIColor whiteColor];
    [textF doBorderWidth:0.5 color:nil cornerRadius:2.0];
    UIImageView *imageV = [YLImageView new];
    imageV.backgroundColor = [UIColor lightGrayColor];
    imageV.contentMode = UIViewContentModeScaleAspectFit;
    imageV.clipsToBounds = YES;
    imageV.userInteractionEnabled = YES;
    [textF doBorderWidth:0.5 color:nil cornerRadius:2.0];
    [imageV sd_setImageWithURL:imageURL placeholderImage:nil options:(SDWebImageRetryFailed | SDWebImageRefreshCached | SDWebImageHandleCookies)];
    
    [alertV.contentView addSubview:textF];
    [alertV.contentView addSubview:imageV];
    [textF mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(alertV.contentView).offset(15);
        make.height.mas_equalTo(25);
        make.bottom.equalTo(alertV.contentView).offset(-10);
    }];
    [imageV mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(alertV.contentView).offset(-15);
        make.left.equalTo(textF.mas_right).offset(10);
        make.width.mas_equalTo(60);
        make.height.mas_equalTo(25);
        make.centerY.equalTo(textF);
    }];
    //Action
    __weak typeof(imageV) weakImageV = imageV;
    [imageV bk_whenTapped:^{
        [weakImageV sd_setImageWithURL:imageURL placeholderImage:nil options:(SDWebImageRetryFailed | SDWebImageRefreshCached | SDWebImageHandleCookies)];
    }];
    __weak typeof(alertV) weakAlertV = alertV;
    [alertV addAction:[SDCAlertAction actionWithTitle:@"取消" style:SDCAlertActionStyleCancel handler:nil]];
    [alertV addAction:[SDCAlertAction actionWithTitle:@"确定" style:SDCAlertActionStyleDefault handler:nil]];
    alertV.shouldDismissBlock =  ^BOOL (SDCAlertAction *action){
        BOOL shouldDismiss = [action.title isEqualToString:@"取消"];
        if (!shouldDismiss) {
            params[@"j_captcha"] = textF.text;
            [[CodingNetAPIClient sharedJsonClient] requestJsonDataWithPath:path withParams:params withMethodType:Post andBlock:^(id data, NSError *error) {
                if (data) {
                    [weakAlertV dismissWithCompletion:^{
                        if (block) {
                            block();
                        }else{
                            [NSObject showHudTipStr:@"验证码正确"];
                        }
                    }];
                }else{
                    [weakImageV sd_setImageWithURL:imageURL placeholderImage:nil options:(SDWebImageRetryFailed | SDWebImageRefreshCached | SDWebImageHandleCookies)];
                }
            }];
        }
        return shouldDismiss;
    };
    [alertV presentWithCompletion:^{
        [textF becomeFirstResponder];
    }];
}


#pragma Other
+ (void)logCookies{
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    [cookies enumerateObjectsUsingBlock:^(NSHTTPCookie *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"cookie: %@", obj.description);
    }];
}

+ (void)preCookieHandle{
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName: @"e_dev",
                                                                NSHTTPCookieValue: @"1",
                                                                NSHTTPCookieDomain: @".coding.net",
                                                                NSHTTPCookieOriginURL: @".coding.net",
                                                                NSHTTPCookiePath: @"/"}];
    [storage setCookie:cookie];
    
    //    [self logCookies];
}

@end
