//
//  Operation.m
//  tuber
//
//  Created by ドラッサル 亜嵐 on 2016/06/09.
//  Copyright © 2016年 ドラッサル 亜嵐. All rights reserved.
//

#import "Operation.h"
#import "AFNetworking.h"

@interface Operation () {
    NSLock* _lock;
    NSArray *_enableCountryNames;
    NSArray *_enableCountryCodes;
}

@end

@implementation Operation

- (void)search:(NSString*)query
       success:(void(^)(id JSON))successHandler
       failure:(void(^)(NSError *error, id JSON))failureHandler {

    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    [params setObject:YOUTUBE_KEY forKey:@"key"];
    [params setObject:query forKey:@"q"];
    [params setObject:@"id,snippet" forKey:@"part"];
    [params setObject:@"JP" forKey:@"regionCode"];
    [params setObject:@"ja-JP" forKey:@"hl"];
    [params setObject:@"50" forKey:@"maxResults"];
    [params setObject:@"video" forKey:@"type"];
    
    params = [self buildParams:params needAuth:NO];
    [self startCustomOperationWithParams:params
                                 reqPath:@"https://www.googleapis.com/%@"
                                    path:@"youtube/v3/search"
                                  method:@"GET"
                                 success:^(id JSON) {
                                     if (successHandler) {
                                         successHandler(JSON);
                                     }
                                 }
                                 failure:^(NSError *error, id JSON) {
                                     //NSLog(@"ERROR %@", error);
                                     if (failureHandler) {
                                         failureHandler(error, JSON);
                                     }
                                 }];
  
    
    
    //NSMutableDictionary *params = [self buildParams:@{COID_KEY:coId, MEMBERID_KEY:memberId, CHANGEDEVICE_SECURITY_KEY:key} needAuth:YES];
    //NSMutableDictionary *params = [NSMutableDictionary dictionary];

    
    //[params setObject:urlString forKey:@"url"];
    /*
    [params setObject:@"AIzaSyAGL0g4CGOR4k5ZDTx9UvNlJPnP2cg8YIY" forKey:@"key"];
    [params setObject:@"video" forKey:@"type"];
    [params setObject:@"relevance" forKey:@"order"];
    [params setObject:@"akb48" forKey:@"q"];
    [params setObject:@"any" forKey:@"videoDuration"];
    [params setObject:@"snippet" forKey:@"part"];
    [params setObject:@"JP" forKey:@"regionCode"];
    [params setObject:@"ja" forKey:@"relevanceLanguage"];
    [params setObject:@"50" forKey:@"maxResults"];
    */
    /*
    params = [self buildParams:params needAuth:NO];
    [self startOperationWithParams:params
                              path:@"api"
                            method:@"GET"
                           success:^(id JSON) {
                               if (successHandler) {
                                   successHandler(JSON);
                               }
                           }
                           failure:^(NSError *error, id JSON) {
                               //NSLog(@"ERROR %@", error);
                               if (failureHandler) {
                                   failureHandler(error, JSON);
                               }
                           }];
     */
}

/*
- (void)search:(NSString*)query
           success:(void(^)(id JSON))successHandler
           failure:(void(^)(NSError *error, id JSON))failureHandler {
    //NSMutableDictionary *params = [self buildParams:@{COID_KEY:coId, MEMBERID_KEY:memberId, CHANGEDEVICE_SECURITY_KEY:key} needAuth:YES];
    NSMutableDictionary *params = [NSMutableDictionary dictionary];

    //NSString * urlString = [NSString stringWithFormat:URL_STRING_SEARCH,query];
    
    [params setObject:query forKey:@"query"];
    [params setObject:@"(all type:/music/artist created:\"The Lady Killer\")" forKey:@"filter"];
    [params setObject:@"10" forKey:@"limit"];
    [params setObject:@"true" forKey:@"indent"];

    //[params setObject:@"AIzaSyAGL0g4CGOR4k5ZDTx9UvNlJPnP2cg8YIY" forKey:@"key"];
    //[params setObject:@"video" forKey:@"type"];
    //[params setObject:@"relevance" forKey:@"order"];
    //[params setObject:@"akb48" forKey:@"q"];
    //[params setObject:@"any" forKey:@"videoDuration"];
    //[params setObject:@"snippet" forKey:@"part"];
    //[params setObject:@"JP" forKey:@"regionCode"];
    //[params setObject:@"ja" forKey:@"relevanceLanguage"];
    //[params setObject:@"50" forKey:@"maxResults"];

    params = [self buildParams:params needAuth:NO];
        
    [self startOperationWithParams:params
                              path:@"search?key=AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc"
                            method:@"POST"
                           success:^(id JSON) {
                               if (successHandler) {
                                   successHandler(JSON);
                               }
                           }
                           failure:^(NSError *error, id JSON) {
                               //NSLog(@"ERROR %@", error);
                               if (failureHandler) {
                                   failureHandler(error, JSON);
                               }
                           }];
}
*/

- (void)details:(NSArray*)listDetail
       success:(void(^)(id JSON))successHandler
       failure:(void(^)(NSError *error, id JSON))failureHandler {

    NSString * detailString = [[NSString alloc] init];
    for(id key in listDetail) {
        if([detailString isEqualToString: @""]) {
            detailString = [NSString stringWithFormat:@"%@",key];
        } else {
            detailString = [NSString stringWithFormat:@"%@,%@",detailString,key];
        }
    }
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    NSString * urlString = [NSString stringWithFormat:URL_STRING_DETAILS,[detailString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]];
    
    [params setObject:urlString forKey:@"url"];

    params = [self buildParams:params needAuth:NO];
    [self startOperationWithParams:params
                              path:@"api"
                            method:@"GET"
                           success:^(id JSON) {
                               if (successHandler) {
                                   successHandler(JSON);
                               }
                           }
                           failure:^(NSError *error, id JSON) {
                               //NSLog(@"ERROR %@", error);
                               if (failureHandler) {
                                   failureHandler(error, JSON);
                               }
                           }];
}

- (void)getVideoInfo:(NSString*)videoId
         success:(void(^)(id JSON))successHandler
         failure:(void(^)(NSError *error, id JSON))failureHandler {
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    [params setObject:YOUTUBE_KEY forKey:@"key"];
    [params setObject:videoId forKey:@"id"];
    [params setObject:@"id,snippet,contentDetails" forKey:@"part"];
    
    params = [self buildParams:params needAuth:NO];
    [self startCustomOperationWithParams:params
                                 reqPath:@"https://www.googleapis.com/%@"
                                    path:@"youtube/v3/videos"
                                  method:@"GET"
                                 success:^(id JSON) {
                                     if (successHandler) {
                                         successHandler(JSON);
                                     }
                                 }
                                 failure:^(NSError *error, id JSON) {
                                     //NSLog(@"ERROR %@", error);
                                     if (failureHandler) {
                                         failureHandler(error, JSON);
                                     }
                                 }];
}

- (void)getImage:(NSString*)urlString
       success:(void(^)(id JSON))successHandler
       failure:(void(^)(NSError *error, id JSON))failureHandler {

    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    params = [self buildParams:params needAuth:NO];
    [self startImageOperationWithParams:params
                                    path:urlString
                                  method:@"GET"
                                 success:^(id JSON) {
                                     if (successHandler) {
                                         successHandler(JSON);
                                     }
                                 }
                                 failure:^(NSError *error, id JSON) {
                                     //NSLog(@"ERROR %@", error);
                                     if (failureHandler) {
                                         failureHandler(error, JSON);
                                     }
                                 }];
}

- (void)getRaw:(NSString*)urlString
         success:(void(^)(id JSON))successHandler
         failure:(void(^)(NSError *error, id JSON))failureHandler {
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    params = [self buildParams:params needAuth:NO];
    [self startRawOperationWithParams:params
                                   path:urlString
                                 method:@"GET"
                                success:^(id JSON) {
                                    if (successHandler) {
                                        successHandler(JSON);
                                    }
                                }
                                failure:^(NSError *error, id JSON) {
                                    //NSLog(@"ERROR %@", error);
                                    if (failureHandler) {
                                        failureHandler(error, JSON);
                                    }
                                }];
}

- (void)streamToFile:(NSString*)urlString
          saveToPath:(NSString*)saveToPath
       progressBlock:(void(^)(double fractionCompleted))progressBlock
             success:(void(^)(NSString *savedTo))successHandler
             failure:(void(^)(NSError *error))failureHandler {
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    
    NSURL *URL = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request
                                                                     progress:^(NSProgress * _Nonnull downloadProgress) {
                                                                          //NSLog(@"Progress: %f", downloadProgress.fractionCompleted);
                                                                           dispatch_async(dispatch_get_main_queue(), ^{
                                                                               progressBlock(downloadProgress.fractionCompleted);
                                                                           });
                                                                      }
                                                                  destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
        NSError *error;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
        NSString *saveToPathFull = [documentsDirectory stringByAppendingPathComponent:saveToPath];
        NSString *saveToFolder = [saveToPathFull stringByDeletingLastPathComponent];
        if (![[NSFileManager defaultManager] fileExistsAtPath:saveToFolder])
        {
            [[NSFileManager defaultManager] createDirectoryAtPath:saveToFolder withIntermediateDirectories:NO attributes:nil error:&error];
        }

        NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
        //return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
        return [documentsDirectoryURL URLByAppendingPathComponent:saveToPath];
    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
        if(!error) {
            //NSLog(@"File downloaded to: %@", filePath);
            successHandler([NSString stringWithFormat:@"%@",filePath]);
        } else {
            failureHandler(error);
        }
    }];
    [downloadTask resume];
}

- (UIImage*)getImageFromFile:(NSString*)filename {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                         NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString* path = [documentsDirectory stringByAppendingPathComponent:
                      [NSString stringWithFormat: @"/save/%@",filename]];
    UIImage* image = [UIImage imageWithContentsOfFile:path];
    return image;
}

# pragma mark - Singleton pattern

static Operation *_sharedOperation;

- (id)init {
    self = [super init];
    if (self) {
        // 初期処理
        _lock = [[NSLock alloc] init];
    }
    return self;
}

+ (instancetype)sharedOperation {
    @synchronized(self) {
        if (_sharedOperation == nil) {
            (void) [[self alloc] init]; // ここでは代入していない
        }
    }
    return _sharedOperation;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (_sharedOperation == nil) {
            _sharedOperation = [super allocWithZone:zone];
            return _sharedOperation;  // 最初の割り当てで代入し、返す
        }
    }
    return nil;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

#pragma mark - Private Methods

- (void)startOperationWithParams:(NSDictionary *)aParams
                            path:(NSString *)pathString
                          method:(NSString *)method
                         success:(void(^)(id JSON))successHandler
                         failure:(void(^)(NSError *error, id JSON))failureHandler {
    [self startOperationWithParams:aParams reqPath:URL_REQUEST_PATH path:pathString method:method success:successHandler failure:failureHandler];
}

- (void)startOperationWithParams:(NSDictionary *)aParams
                         reqPath:(NSString *)reqPathStr
                            path:(NSString *)pathString
                          method:(NSString *)method
                         success:(void(^)(id JSON))successHandler
                         failure:(void(^)(NSError *error, id JSON))failureHandler {
    
    // form-urlencoded request
    NSString *path = [NSString stringWithFormat:reqPathStr, pathString];
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",BASE_URL,path]];

    // set self.manager only if it hasn't been created yet
    if(!self.manager)
    {
        self.manager = [AFHTTPSessionManager manager]; // 71%
        //self.manager.requestSerializer = [AFJSONRequestSerializer serializer];
        self.manager.responseSerializer = [AFJSONResponseSerializer serializer]; // 9.7%
        self.manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"application/x-www-form-urlencoded", nil];

    }
    /*
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     [manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
     */
    
    NSMutableDictionary *params = [self buildParams:aParams needAuth:NO];
    /*
     NSMutableURLRequest *request = [httpClient requestWithMethod:method
     path:path
     parameters:params];
     [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
     */
    
    if([method isEqualToString:@"GET"]) {
        self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        [self.manager GET:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            if([responseObject isKindOfClass:[NSDictionary class]]) {
                if(successHandler) {
                    successHandler(responseObject);
                }
            }
            else {
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
                NSLog(@"[Operation] => resultObject: %@", response);
                if(successHandler) {
                    successHandler(response);
                }
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    } else if([method isEqualToString:@"POST"]) {
        [self.manager POST:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            if([responseObject isKindOfClass:[NSDictionary class]]) {
                if(successHandler) {
                    successHandler(responseObject);
                }
            }
            else {
                NSLog(@"[Operation] => resultObject: %@", responseObject);
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
                if(successHandler) {
                    successHandler(response);
                }
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    }
    
    //NSLog(@"[Operation] => startResuest: %@", [[request URL] absoluteString]);
    NSLog(@"[Operation] => params: %@", params);
}

- (void)startCustomOperationWithParams:(NSDictionary *)aParams
                                  path:(NSString *)pathString
                                method:(NSString *)method
                               success:(void(^)(id JSON))successHandler
                               failure:(void(^)(NSError *error, id JSON))failureHandler {
    [self startCustomOperationWithParams:aParams reqPath:@"%@" path:pathString method:method success:successHandler failure:failureHandler];
}

- (void)startCustomOperationWithParams:(NSDictionary *)aParams
                         reqPath:(NSString *)reqPathStr
                            path:(NSString *)pathString
                          method:(NSString *)method
                         success:(void(^)(id JSON))successHandler
                         failure:(void(^)(NSError *error, id JSON))failureHandler {
    
    // form-urlencoded request
    NSString *path = [NSString stringWithFormat:reqPathStr, pathString];
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",path]];
    
    // set self.manager only if it hasn't been created yet
    if(!self.managerCustom)
    {
        self.managerCustom = [AFHTTPSessionManager manager]; // 71%
        //self.manager.requestSerializer = [AFJSONRequestSerializer serializer];
        self.managerCustom.responseSerializer = [AFHTTPResponseSerializer serializer]; // 9.7%
        self.managerCustom.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"application/x-www-form-urlencoded", nil];
        
    }
    /*
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     [manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
     */
    
    NSMutableDictionary *params = [self buildParams:aParams needAuth:NO];
    /*
     NSMutableURLRequest *request = [httpClient requestWithMethod:method
     path:path
     parameters:params];
     [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
     */
    
    if([method isEqualToString:@"GET"]) {
        [self.managerCustom GET:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            if([responseObject isKindOfClass:[NSDictionary class]]) {
                if(successHandler) {
                    successHandler(responseObject);
                }
            }
            else {
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
                NSLog(@"[Operation] => resultObject: %@", response);
                if(!response) {
                    NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init];
                    NSString * responseString = [[NSString alloc] initWithBytes:(char *)[responseObject bytes] length:[responseObject length] encoding:NSUTF8StringEncoding];
                    NSArray *urlComponents = [responseString componentsSeparatedByString:@"&"];

                    for (NSString *keyValuePair in urlComponents)
                    {
                        NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="];
                        NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding];
                        NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding];
                        
                        value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
                        value = [value stringByRemovingPercentEncoding];

                        [queryStringDictionary setObject:value forKey:key];
                    }
                    response = queryStringDictionary;
                }
                if(successHandler) {
                    successHandler(response);
                }
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    } else if([method isEqualToString:@"POST"]) {
        [self.managerCustom POST:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            if([responseObject isKindOfClass:[NSDictionary class]]) {
                if(successHandler) {
                    successHandler(responseObject);
                }
            }
            else {
                NSLog(@"[Operation] => resultObject: %@", responseObject);
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
                if(successHandler) {
                    successHandler(response);
                }
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    }
    
    //NSLog(@"[Operation] => startResuest: %@", [[request URL] absoluteString]);
    NSLog(@"[Operation] => params: %@", params);
}

- (void)startImageOperationWithParams:(NSDictionary *)aParams
                                  path:(NSString *)pathString
                                method:(NSString *)method
                               success:(void(^)(id JSON))successHandler
                               failure:(void(^)(NSError *error, id JSON))failureHandler {
    [self startImageOperationWithParams:aParams reqPath:@"%@" path:pathString method:method success:successHandler failure:failureHandler];
}

- (void)startImageOperationWithParams:(NSDictionary *)aParams
                               reqPath:(NSString *)reqPathStr
                                  path:(NSString *)pathString
                                method:(NSString *)method
                               success:(void(^)(id JSON))successHandler
                               failure:(void(^)(NSError *error, id JSON))failureHandler {
   
    // form-urlencoded request
    NSString *path = [NSString stringWithFormat:reqPathStr, pathString];
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",path]];
    
    // set self.manager only if it hasn't been created yet
    if(!self.managerImage)
    {
        self.managerImage = [AFHTTPSessionManager manager]; // 71%
        //self.managerImage.requestSerializer = [AFJSONRequestSerializer serializer];
        self.managerImage.responseSerializer = [AFImageResponseSerializer serializer]; // 9.7%
    }
    /*
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
     */
    
    NSMutableDictionary *params = [self buildParams:aParams needAuth:NO];
    /*
     NSMutableURLRequest *request = [httpClient requestWithMethod:method
     path:path
     parameters:params];
     [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
     */
    
    if([method isEqualToString:@"GET"]) {
        [self.managerImage GET:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            NSLog(@"[Operation] => resultObject: %@", responseObject);
            if(successHandler) {
                successHandler(responseObject);
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    } else if([method isEqualToString:@"POST"]) {
        [self.managerImage POST:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            NSLog(@"[Operation] => resultObject: %@", responseObject);
            if(successHandler) {
                successHandler(responseObject);
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    }
    
    //NSLog(@"[Operation] => startResuest: %@", [[request URL] absoluteString]);
    NSLog(@"[Operation] => params: %@", params);
}

- (void)startRawOperationWithParams:(NSDictionary *)aParams
                                 path:(NSString *)pathString
                               method:(NSString *)method
                              success:(void(^)(id JSON))successHandler
                              failure:(void(^)(NSError *error, id JSON))failureHandler {
    [self startRawOperationWithParams:aParams reqPath:@"%@" path:pathString method:method success:successHandler failure:failureHandler];
}

- (void)startRawOperationWithParams:(NSDictionary *)aParams
                              reqPath:(NSString *)reqPathStr
                                 path:(NSString *)pathString
                               method:(NSString *)method
                              success:(void(^)(id JSON))successHandler
                              failure:(void(^)(NSError *error, id JSON))failureHandler {
    
    // form-urlencoded request
    NSString *path = [NSString stringWithFormat:reqPathStr, pathString];
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",path]];
    
    // set self.manager only if it hasn't been created yet
    if(!self.managerRaw)
    {
        self.managerRaw = [AFHTTPSessionManager manager]; // 71%
        //self.managerRaw.responseSerializer = [AFJSONRequestSerializer serializer];
        //self.managerRaw.responseSerializer = [AFImageResponseSerializer serializer]; // 9.7%
        self.managerRaw.responseSerializer = [AFHTTPResponseSerializer serializer]; // 9.7%
    }
    /*
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
     [manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
     */
    
    NSMutableDictionary *params = [self buildParams:aParams needAuth:NO];
    /*
     NSMutableURLRequest *request = [httpClient requestWithMethod:method
     path:path
     parameters:params];
     [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
     */
    
    if([method isEqualToString:@"GET"]) {
        [self.managerRaw GET:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            if(successHandler) {
                successHandler(responseObject);
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    } else if([method isEqualToString:@"POST"]) {
        [self.managerRaw POST:URL.absoluteString parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            if(successHandler) {
                successHandler(responseObject);
            }
        } failure:^(NSURLSessionTask *operation, NSError *error) {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }];
    }
    
    //NSLog(@"[Operation] => startResuest: %@", [[request URL] absoluteString]);
    NSLog(@"[Operation] => params: %@", params);
}

/*
- (void)startOperationWithParams:(NSDictionary *)aParams
                         reqPath:(NSString *)reqPathStr
                            path:(NSString *)pathString
                          method:(NSString *)method
                         success:(void(^)(id JSON))successHandler
                         failure:(void(^)(NSError *error, id JSON))failureHandler {
    
    // form-urlencoded request
    NSString *path = [NSString stringWithFormat:reqPathStr, pathString];
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",BASE_URL,path]];
    NSMutableDictionary *params = [self buildParams:aParams needAuth:NO];

    
    

    
    
    
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    
    NSMutableURLRequest *req = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URL.absoluteString parameters:nil error:nil];
    
    req.timeoutInterval= [[[NSUserDefaults standardUserDefaults] valueForKey:@"timeoutInterval"] longValue];
    [req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [req setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    //[req setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
    

    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:params forKey:@"Some Key Value"];
    [archiver finishEncoding];
    // Here, data holds the serialized version of your dictionary
    [req setHTTPBody:data];
    
    
    [[manager dataTaskWithRequest:req completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        
        if (!error) {
            if([responseObject isKindOfClass:[NSDictionary class]]) {
                if(successHandler) {
                    successHandler(responseObject);
                }
            }
            else {
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
                NSLog(@"[Operation] => resultObject: %@", response);
                if(successHandler) {
                    successHandler(response);
                }
            }
        } else {
            //NSLog(@"[Operation] => resultObject: %@", responseObject);
            NSLog(@"[Operation] => error: %@", error);
            if (failureHandler) {
                //failureHandler(error, responseObject);
                failureHandler(error, nil);
            }
        }
    }] resume];
    
    //NSLog(@"[Operation] => startResuest: %@", [[request URL] absoluteString]);
    NSLog(@"[Operation] => params: %@", params);
}
 */

# pragma mark - Network management methods

- (NSMutableDictionary *)buildParams:(NSDictionary *)params needAuth:(BOOL)needAuth {
    // APIの基本パラメータを生成
    NSMutableDictionary *result = [NSMutableDictionary dictionary];
    if (params) {
        [result setValuesForKeysWithDictionary:params];
    }
    if (needAuth) {
        NSString *username = USER_USERID;
        if (!username)
            username = @"";
        NSString *password = USER_PASSWORD;
        if (!password)
            password = @"";
        [result setObject:username forKey:KEY_USER_USERID];
        [result setObject:password forKey:KEY_USER_PASSWORD];
    }
    //[result setObject:@"ios" forKey:AGENT_KEY];
    //[result setObject:@"vname" forKey:VNAME_KEY];
    return result;
}

@end
