//
//  networkMaker.m
//  Project
//
//  Created by Vae on 2018/12/18.
//

#import "BasicNetworkMaker.h"
#import "CocoaUtils.h"
#import "Lang.h"
#import "NetUtils.h"
#import "Vars.h"
#import <BlocksKit/BlocksKit.h>
@import AFNetworking;

@interface BasicNetworkMaker()
@end

@implementation BasicNetworkMaker

#pragma mark - init

- (instancetype)init{
	self = [super init];
	if (self) {
		self.manager = [AFHTTPSessionManager manager];
		self.request = [[NSMutableURLRequest alloc] init];
		self.method = @"GET";
	}
	return self;
}

#pragma mark - Network build config

-(NetWorkChainableString)makeUrl{
	return NetWorkChainableString(string){
		self.urlString = string;
		return self;
	};
}

-(NetWorkChainableString)makeMethod{
	return NetWorkChainableString(string){
		self.method = string;
		return self;
	};
}

-(NetWorkChainableDic)makeHeader{
	return NetWorkChainableDic(dic){
		self.header = dic;
		return self;
	};
}

-(NetWorkChainableNumber)makeRequestEncoding{
	return NetWorkChainableNumber(number){
		self.requestEncoding = number.integerValue;
		return self;
	};
}

-(NetWorkChainableString)makeRequestDataType{
	return NetWorkChainableString(string){
		self.requestDataType = string;
		return self;
	};
}

-(NetWorkChainableString)makeResponseDataType{
	return NetWorkChainableString(string){
		self.responseDataType = string;
		return self;
	};
}

-(NetWorkChainableNumber)makeTimeoutInterval{
	return NetWorkChainableNumber(number){
		self.timeoutInterval = number.doubleValue;
		return self;
	};
}

-(NetWorkChainableBlock)makeUploadProgressBlock{
	return NetWorkChainableBlock(block){
		self.uploadProgressBlock = block;
		return self;
	};
}

-(NetWorkChainableDic)makeParamter{
	return NetWorkChainableDic(dic){
		self.paramter = dic;
		return self;
	};
}

- (NetWorkChainableHandle)makeBeforeSendHandle{
	return NetWorkChainableHandle(handle){
		self.beforeSendHandle = handle;
		return self;
	};
}

- (NetWorkChainableHandle)makeCompleteHandle{
	return NetWorkChainableHandle(handle){
		self.completeHandle = handle;
		return self;
	};
}

-(NetWorkChainableFinish)makeErrorHandle{
	return NetWorkChainableFinish(handle){
		self.errorHandle = handle;
		return self;
	};
}

- (NetWorkChainableFinish)makeSuccessHandle{
	return NetWorkChainableFinish(handle){
		 self.successHandle = handle;
		return self;
	};
}

-(NetWorkChainableMultipartFormData)makeConstructingBodyWithBlock{
	return NetWorkChainableMultipartFormData(formData){
		self.formDataBlock = formData;
		return self;
	};
}

#pragma mark - Action

- (AnyPromise *)build{

	UIViewController *this = [CocoaUtils topMostViewController];
	
	return 	[AnyPromise promiseWithValue:@1].then(^{
		self.beforeSendHandle ? self.beforeSendHandle() : [CocoaUtils showBusyIndicator:this.view];
	}).then(^{
		return self.formDataBlock ? [self uploadNetworkTask] : [self netWorkTask];
	}).then(^(id responseObject){
		self.successHandle(responseObject);
	}).catch(^(NSError *error){
		self.errorHandle ? self.errorHandle(error) : [CocoaUtils showNotificationWithMessage:error.localizedDescription];
	}).ensure(^{
		self.completeHandle ? self.completeHandle() : [CocoaUtils hideBusyIndicator:this.view];
	});
}

-(AnyPromise *)performBatchNetWorkRequest:(NSArray<AnyPromise *> *)array{
	
	UIViewController *this = [CocoaUtils topMostViewController];
	return 	[AnyPromise promiseWithValue:@1].then(^{
		self.beforeSendHandle ? self.beforeSendHandle() : [CocoaUtils showBusyIndicator:this.view];
	}).then(^{
	 return PMKWhen(array);
	}).catch(^(NSError *error){
		self.errorHandle ? self.errorHandle(error) : [CocoaUtils showNotificationWithMessage:error.localizedDescription];
	}).ensure(^{
		self.completeHandle ? self.completeHandle() : [CocoaUtils hideBusyIndicator:this.view];
	});
}

#pragma mark - public

- (void)configManger{
	NSString *requestDataType = [self.requestDataType uppercaseString];
	if (![StringUtils isEmpty:requestDataType]) {
		if ([requestDataType isEqualToString:@"JSON"]) {
			self.manager.requestSerializer = [AFJSONRequestSerializer serializer];
		}
	}

	NSString *responseDataType = [self.responseDataType uppercaseString];
	if(![StringUtils isEmpty:responseDataType]){
		if ([responseDataType isEqualToString:@"TEXT"]) {
			self.manager.responseSerializer = [AFEncodedTEXTResponseSerializer serializer];
		}else if ([responseDataType isEqualToString:@"JSON"]){
			self.manager.responseSerializer = [AFEncodedJSONResponseSerializer serializer];
		}else{
			self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
		}
	}
		
	if (self.timeoutInterval > 0) {
		self.manager.requestSerializer.timeoutInterval = self.timeoutInterval;
	}
	
	if (self.requestEncoding > 0) {
		[self.manager.requestSerializer setStringEncoding:self.requestEncoding];
	}
	
}

-(void)configRequest{
	self.request = [self.manager.requestSerializer requestWithMethod:self.method URLString:self.urlString parameters:self.paramter error:NULL];
}

- (AnyPromise *)netWorkTask{
	[self configRequest];
	[self configManger];
	
	[self.header bk_each:^(NSString *key, NSString *value) {
		[self.manager.requestSerializer setValue:value forHTTPHeaderField:key];
	}];

#ifdef DEBUG
	NSLog(@"%@ %@ %@ %@",self.method,self.paramter,self.request.URL,self.request.HTTPBody ? [[NSString alloc] initWithData:self.request.HTTPBody encoding:self.manager.requestSerializer.stringEncoding] : @"");
#endif
	
	return 	[AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {
		[[self.manager dataTaskWithRequest:self.request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
			if (error) {
				resolver(error);
			}else{
				resolver(responseObject);
			}
		}] resume];
	}];
}

-(AnyPromise *)uploadNetworkTask{
	self.request = 	[self.manager.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:self.urlString parameters:self.paramter constructingBodyWithBlock:self.formDataBlock error:NULL];
	self.manager.responseSerializer = [AFEncodedTEXTResponseSerializer serializer];
	self.manager.requestSerializer.stringEncoding = [Vars charset];
	
	[self.header bk_each:^(NSString *key, NSString *value) {
		[self.manager.requestSerializer setValue:value forHTTPHeaderField:key];
	}];
#ifdef DEBUG
	NSLog(@" %@ %@ %@",self.paramter,self.request.URL,self.request.HTTPBody ? [[NSString alloc] initWithData:self.request.HTTPBody encoding:self.manager.requestSerializer.stringEncoding] : @"");
#endif
	return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {
		[[self.manager uploadTaskWithStreamedRequest:self.request progress:self.uploadProgressBlock ? ^(NSProgress *  uploadProgress) {
			dispatch_async(dispatch_get_main_queue(), ^{
				self.uploadProgressBlock(uploadProgress.fractionCompleted);
			});
		}:nil completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
			if (error) {
				resolver(error);
			}else{
				resolver(responseObject);
			}
		}] resume];
	}];
}


@end
