//
//  NetworkMaker.m
//  Project
//
//  Created by Vae on 2018/12/21.
//

#import "CocoaUtils.h"
#import "Lang.h"
#import "NetUtils.h"
#import "NetworkMaker.h"
#import "NetworkMakerBlocks.h"
#import "Vars.h"
#import <BlocksKit/BlocksKit.h>
#import <RestKit/RKDictionaryUtilities.h>
#import <RestKit/RKURLEncodedSerialization.h>
@import AFNetworking;

@interface NetworkMaker()
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSString *namespace;
@property(nonatomic, assign) NetworkType networkType;
@end

@implementation NetworkMaker

#pragma mark - config Network

-(NetWorkChainableNetworkType)makeNetworkType{
	return NetWorkChainableNetworkType(type){
		self.networkType = type;
		return self;
	};
}

-(NetWorkChainableString)makeName{
	return NetWorkChainableString(string){
		self.name = string;
		return self;
	};
}

-(NetWorkChainableString)makeNamespace{
	return NetWorkChainableString(string){
		self.namespace = string;
		return self;
	};
}

#pragma mark - Action

-(void)configManger{
	if ([StringUtils isEmpty:self.requestDataType] && [StringUtils isEmpty:self.responseDataType]) {
		switch (self.networkType) {
			case NetworkTypeTEXT || NetworkTypeXML:
				self.manager.responseSerializer = [AFEncodedTEXTResponseSerializer serializer];
				self.manager.requestSerializer.stringEncoding = [Vars charset];
				break;
			case NetworkTypeJSON:
				self.manager.responseSerializer = [AFEncodedJSONResponseSerializer serializer];
				self.manager.requestSerializer.stringEncoding = [Vars charset];
				self.manager.responseSerializer.acceptableContentTypes = nil;
				break;
			case NetworkTypeREST:
				self.manager.requestSerializer = [AFJSONRequestSerializer serializer];
				self.manager.responseSerializer = [AFEncodedJSONResponseSerializer serializer];
				break;
			case NetworkTypeSOAP:
				self.manager.responseSerializer = [AFEncodedTEXTResponseSerializer serializer];
				break;
			case NetworkTypeUpload:
				self.manager.responseSerializer = [AFEncodedTEXTResponseSerializer serializer];
				self.manager.requestSerializer.stringEncoding = [Vars charset];
				break;
			default:
				break;
		}
	}
	
	if (self.networkType != NetworkTypeREST) {
		NSStringEncoding stringEncoding = self.manager.requestSerializer.stringEncoding;
		[self.manager.requestSerializer setQueryStringSerializationWithBlock:^NSString * (NSURLRequest *request, id parameters, NSError * *error) {
			return RKURLEncodedStringFromDictionaryWithEncoding(parameters, stringEncoding);
		}];
	}
	[super configManger];
}

- (AnyPromise *)build{
	[self configManger];
	[self configRequest];
	
	UIViewController *this = [CocoaUtils topMostViewController];
	
	return 	[AnyPromise promiseWithValue:@1].then(^{
		self.beforeSendHandle ? self.beforeSendHandle() : [CocoaUtils showBusyIndicator:this.view];
	}).then(^{
		if (self.networkType == NetworkTypeUpload) {
			return 	[self uploadNetworkTask];
		}else{
			return [self netWorkTask];
		}
	}).then(^(id responseObject){
		[self handleResponse:responseObject];
	}).catch(^(NSError *error){
		error =	[NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorUnknown userInfo:@{ NSLocalizedDescriptionKey : [Vars responseException] }];
		self.errorHandle ? self.errorHandle(error) : [CocoaUtils showNotificationWithMessage:error.localizedDescription];
	}).ensure(^{
		self.completeHandle ? self.completeHandle() : [CocoaUtils hideBusyIndicator:this.view];
	});
}

-(void)configRequest{
	NSString *query;
	[super configRequest];
	switch (self.networkType) {
		case NetworkTypeSOAP:
			query = [self javaSOAPEnvelope:[CocoaUtils xmlStringWithProperties:self.paramter] name:self.name namespace:self.namespace];
	#if DEBUG
			NSLog(@"SOAP %@ %@", self.urlString, query);
	#endif
			self.request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]];
			self.request.HTTPMethod = @"POST";
			self.request.HTTPBody = [query dataUsingEncoding:NSUTF8StringEncoding];
			[self.request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
			break;
		case NetworkTypeUpload:
			self.request = 	[self.manager.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:self.urlString parameters:self.paramter constructingBodyWithBlock:self.formDataBlock error:NULL];
			break;
		default:
			break;
	}
}

#pragma mark - private

- (NSString *)javaSOAPEnvelope:(NSString *)string name:(NSString *)name namespace:(NSString *)namespace {
	NSString *body = [NSString stringWithFormat:@"<%@ xmlns=\"%@\">%@</%@>", name, namespace, string, name];
	return [NSString stringWithFormat:@"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body>%@</soap:Body></soap:Envelope>", body];
}


-(NSString *)normalizeXmlString:(NSString *)xmlString {
	if ([StringUtils isEmpty:xmlString]) {
		return xmlString;
	}
	xmlString = [StringEscapeUtils unescapeXml:xmlString];
	xmlString = [xmlString stringByReplacingOccurrencesOfString:@", <DATA> line" withString:@", DATA line"];
	return xmlString;
}

-(void)handleResponse:(id)response{
	switch (self.networkType) {
		case NetworkTypeXML:
			self.successHandle([self normalizeXmlString:response]);
			break;
		case NetworkTypeSOAP:
			self.successHandle([StringEscapeUtils unescapeXml:response]);
			break;
		default:
			self.successHandle(response);
			break;
	}
}

@end
