<commit_before>//
//  NetworkRequest.swift
//  kapi-kaffeine
//
//  Created by <NAME> on 2017/5/1.
//  Copyright © 2017年 kapi-kaffeine. All rights reserved.
//

import Foundation
import Alamofire
import ObjectMapper
import SwiftyJSON

public struct errorInformation {
    
    let error: Error
    let statusCode: Int?
    let responseBody: KPErrorResponseModel?
    let errorCode: String?
    
    init(error: Error, data: Data?, urlResponse: HTTPURLResponse?) {
        self.error = error
        let json = String(data: data ?? Data(), encoding: String.Encoding.utf8)
        responseBody = KPErrorResponseModel(JSONString:json!)
        statusCode = urlResponse?.statusCode
        errorCode = responseBody?.errorCode
    }
}

public enum NetworkRequestError: Error {
    case invalidData
    case apiError(errorInformation: errorInformation)
    case unknownError
    case noNetworkConnection
    case resultUnavailable
}

public typealias RawJsonResult = JSON

// MARK: Request

public protocol NetworkRequest {
    
    associatedtype ResponseType
    
    // Required
    /// End Point.
    /// e.g. /cards/:id/dislike
    var endpoint: String { get }
    
    /// Will transform given data to requested type of response.
    var responseHandler: (Data) throws -> ResponseType { get }
    
    // Optional
    var baseURL: String { get }
    /// Method to make the request. E.g. get, post.
    
    var method: Alamofire.HTTPMethod { get }
    /// Parameter encoding. E.g. JSON, URLEncoding.default.
    
    var encoding: Alamofire.ParameterEncoding { get }
    
    var parameters: [String : Any]? { get }
    var headers: [String : String] { get }
    
    /// Client that helps you to make reqeust.
    var networkClient: NetworkClientType { get }
    
}

extension NetworkRequest {
    
    public var url: String { return baseURL + endpoint}
//    public var baseURL: String { return "https://kapi-v2-test.herokuapp.com/api/v2" }
//    public var baseURL: String { return "https://api.kapi.tw/api/v2" }
    public var baseURL: String { return "http://35.201.206.7/api/v2" }
    public var method: Alamofire.HTTPMethod { return .get }
    public var encoding: Alamofire.ParameterEncoding { return method == .get ?
        URLEncoding.default :
        JSONEncoding.default }
    
    public var parameters: [String : AnyObject] { return [:] }
    public var headers: [String : String] {
        return ["token": (KPUserManager.sharedManager.currentUser?.accessToken) ?? ""]
    }
    
    public var networkClient: NetworkClientType { return NetworkClient() }
    
}

extension NetworkRequest where ResponseType: Mappable {
    
    // 輸入 Data 型別，回傳 ResponseType
    public var responseHandler: (Data) throws -> ResponseType { return jsonResponseHandler }
    public var arrayResponseHandler: (Data) throws -> [ResponseType] { return jsonArrayResponseHandler }
    
    private func jsonResponseHandler(_ data: Data) throws -> ResponseType {
        let json = String(data: data, encoding: String.Encoding.utf8)
        
        if let response = Mapper<ResponseType>().map(JSONString: json!) {
            return response
        } else {
            throw NetworkRequestError.invalidData
        }
    }
    
    private func jsonArrayResponseHandler(_ data: Data) throws -> [ResponseType] {
        let json = String(data: data , encoding: String.Encoding.utf8)
        if let responses = Mapper<ResponseType>().mapArray(JSONString: json!) {
            return responses
        } else {
            throw NetworkRequestError.invalidData
        }
    }
}

extension NetworkRequest where ResponseType == RawJsonResult {
    
    public var responseHandler: (Data) throws -> ResponseType {
        return rawJsonResponseHandler
    }

    private func rawJsonResponseHandler(_ data: Data) throws -> ResponseType {
        if let responseResult = JSON(data: data).dictionary?["result"] {
            if responseResult.boolValue {
                return JSON(data: data)
            } else {
                throw NetworkRequestError.resultUnavailable
            }
        }
        return JSON(data: data)
    }
}


// MARK: Upload Request

public protocol NetworkUploadRequest {
    
    associatedtype ResponseType
    
    var endpoint: String { get }
    
    var responseHandler: (Data) throws -> ResponseType { get }
    
    // Optional
    var baseURL: String { get }
    
    var method: Alamofire.HTTPMethod { get }
    
    var threshold: UInt64 { get }

    var parameters: [String : Any]? { get }

    var headers: [String : String] { get }
    
    var fileData: Data? { get }
    var fileKey: String? { get }
    var fileName: String? { get }
    var mimeType: String? { get }
    
    /// Client that helps you to make reqeust.
    var networkClient: NetworkClientType { get }
    
}

extension NetworkUploadRequest {
    
    public var url: String { return baseURL + endpoint}
//    public var baseURL: String {return "https://kapi-v2-test.herokuapp.com/api/v2"}
//    public var baseURL: String { return "https://api.kapi.tw/api/v2" }
    public var baseURL: String { return "http://192.168.127.12/api/v2" }
    public var method: Alamofire.HTTPMethod { return .post }
    
    public var threshold: UInt64 { return 100_000_000 }
    public var parameters: [String : AnyObject] { return [:] }
    public var headers: [String : String] { return ["Content-Type":"multipart/form-data",
                                                    "User-Agent":"iReMW4K4fyWos"] }
    
    public var networkClient: NetworkClientType { return NetworkClient() }
    
}

extension NetworkUploadRequest where ResponseType: Mappable {
    
    // 輸入 Data 型別，回傳 ResponseType
    public var responseHandler: (Data) throws -> ResponseType { return jsonResponseHandler }
    public var arrayResponseHandler: (Data) throws -> [ResponseType] { return jsonArrayResponseHandler }
    
    private func jsonResponseHandler(_ data: Data) throws -> ResponseType {
        let json = String(data: data, encoding: String.Encoding.utf8)
        
        if let response = Mapper<ResponseType>().map(JSONString: json!) {
            return response
        } else {
            throw NetworkRequestError.invalidData
        }<commit_msg>Update settings<commit_after>//
//  NetworkRequest.swift
//  kapi-kaffeine
//
//  Created by <NAME> on 2017/5/1.
//  Copyright © 2017年 kapi-kaffeine. All rights reserved.
//

import Foundation
import Alamofire
import ObjectMapper
import SwiftyJSON

public struct errorInformation {
    
    let error: Error
    let statusCode: Int?
    let responseBody: KPErrorResponseModel?
    let errorCode: String?
    
    init(error: Error, data: Data?, urlResponse: HTTPURLResponse?) {
        self.error = error
        let json = String(data: data ?? Data(), encoding: String.Encoding.utf8)
        responseBody = KPErrorResponseModel(JSONString:json!)
        statusCode = urlResponse?.statusCode
        errorCode = responseBody?.errorCode
    }
}

public enum NetworkRequestError: Error {
    case invalidData
    case apiError(errorInformation: errorInformation)
    case unknownError
    case noNetworkConnection
    case resultUnavailable
}

public typealias RawJsonResult = JSON

// MARK: Request

public protocol NetworkRequest {
    
    associatedtype ResponseType
    
    // Required
    /// End Point.
    /// e.g. /cards/:id/dislike
    var endpoint: String { get }
    
    /// Will transform given data to requested type of response.
    var responseHandler: (Data) throws -> ResponseType { get }
    
    // Optional
    var baseURL: String { get }
    /// Method to make the request. E.g. get, post.
    
    var method: Alamofire.HTTPMethod { get }
    /// Parameter encoding. E.g. JSON, URLEncoding.default.
    
    var encoding: Alamofire.ParameterEncoding { get }
    
    var parameters: [String : Any]? { get }
    var headers: [String : String] { get }
    
    /// Client that helps you to make reqeust.
    var networkClient: NetworkClientType { get }
    
}

extension NetworkRequest {
    
    public var url: String { return baseURL + endpoint}
//    public var baseURL: String { return "https://kapi-v2-test.herokuapp.com/api/v2" }
    public var baseURL: String { return "https://api.kapi.tw/api/v2" }
//    public var baseURL: String { return "http://35.201.206.7/api/v2" }
    public var method: Alamofire.HTTPMethod { return .get }
    public var encoding: Alamofire.ParameterEncoding { return method == .get ?
        URLEncoding.default :
        JSONEncoding.default }
    
    public var parameters: [String : AnyObject] { return [:] }
    public var headers: [String : String] {
        return ["token": (KPUserManager.sharedManager.currentUser?.accessToken) ?? ""]
    }
    
    public var networkClient: NetworkClientType { return NetworkClient() }
    
}

extension NetworkRequest where ResponseType: Mappable {
    
    // 輸入 Data 型別，回傳 ResponseType
    public var responseHandler: (Data) throws -> ResponseType { return jsonResponseHandler }
    public var arrayResponseHandler: (Data) throws -> [ResponseType] { return jsonArrayResponseHandler }
    
    private func jsonResponseHandler(_ data: Data) throws -> ResponseType {
        let json = String(data: data, encoding: String.Encoding.utf8)
        
        if let response = Mapper<ResponseType>().map(JSONString: json!) {
            return response
        } else {
            throw NetworkRequestError.invalidData
        }
    }
    
    private func jsonArrayResponseHandler(_ data: Data) throws -> [ResponseType] {
        let json = String(data: data , encoding: String.Encoding.utf8)
        if let responses = Mapper<ResponseType>().mapArray(JSONString: json!) {
            return responses
        } else {
            throw NetworkRequestError.invalidData
        }
    }
}

extension NetworkRequest where ResponseType == RawJsonResult {
    
    public var responseHandler: (Data) throws -> ResponseType {
        return rawJsonResponseHandler
    }

    private func rawJsonResponseHandler(_ data: Data) throws -> ResponseType {
        if let responseResult = JSON(data: data).dictionary?["result"] {
            if responseResult.boolValue {
                return JSON(data: data)
            } else {
                throw NetworkRequestError.resultUnavailable
            }
        }
        return JSON(data: data)
    }
}


// MARK: Upload Request

public protocol NetworkUploadRequest {
    
    associatedtype ResponseType
    
    var endpoint: String { get }
    
    var responseHandler: (Data) throws -> ResponseType { get }
    
    // Optional
    var baseURL: String { get }
    
    var method: Alamofire.HTTPMethod { get }
    
    var threshold: UInt64 { get }

    var parameters: [String : Any]? { get }

    var headers: [String : String] { get }
    
    var fileData: Data? { get }
    var fileKey: String? { get }
    var fileName: String? { get }
    var mimeType: String? { get }
    
    /// Client that helps you to make reqeust.
    var networkClient: NetworkClientType { get }
    
}

extension NetworkUploadRequest {
    
    public var url: String { return baseURL + endpoint}
//    public var baseURL: String {return "https://kapi-v2-test.herokuapp.com/api/v2"}
    public var baseURL: String { return "https://api.kapi.tw/api/v2" }
//    public var baseURL: String { return "http://35.201.206.7/api/v2" }
    public var method: Alamofire.HTTPMethod { return .post }
    
    public var threshold: UInt64 { return 100_000_000 }
    public var parameters: [String : AnyObject] { return [:] }
    public var headers: [String : String] { return ["Content-Type":"multipart/form-data",
                                                    "User-Agent":"iReMW4K4fyWos"] }
    
    public var networkClient: NetworkClientType { return NetworkClient() }
    
}

extension NetworkUploadRequest where ResponseType: Mappable {
    
    // 輸入 Data 型別，回傳 ResponseType
    public var responseHandler: (Data) throws -> ResponseType { return jsonResponseHandler }
    public var arrayResponseHandler: (Data) throws -> [ResponseType] { return jsonArrayResponseHandler }
    
    private func jsonResponseHandler(_ data: Data) throws -> ResponseType {
        let json = String(data: data, encoding: String.Encoding.utf8)
        
        if let response = Mapper<ResponseType>().map(JSONString: json!) {
            return response
        } else {
            throw NetworkRequestError.invalidData
        }
{'fraction_non_alphanumeric': 0.09570375120230844, 'fraction_numerical': 0.008977236293683874, 'mean_word_length': 2.5345609065155807, 'pattern_counts': {'":': 6, '<': 11, '<?xml version=': 0, '>': 33, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6065276', 'n_tokens_mistral': 3530, 'n_tokens_neox': 3452, 'n_words': 1001}