<commit_before>//
//  ResponseConverters.swift
//  ElasticSwift
//
//  Created by <NAME> on 7/4/19.
//

import Foundation
import ElasticSwiftCore

/// closure that handles `HTTPResponse`
/// - Parameters:
///    - result: result with either a success http response or Error
public typealias HTTPResponseHandler = (_ result: Result<HTTPResponse, Error>) -> Void

/// closure that handles codable result
/// - Parameters:
///    - result: result with either a success T response or Error
public typealias ResultCallback<T: Codable> = (_ result: Result<T, Error>) -> Void

/// closure that handles result of response conversion
/// - Parameters:
///     - serializer: serializer to use for response converstion
///     - callback: closure to be called after conversion.
public typealias ResponseConverter<T: Codable> = (_ serializer: Serializer, _ callback: @escaping ResultCallback<T>) -> HTTPResponseHandler


/// Classs with various response converters
public class ResponseConverters {
    
    /// Utility class private initializer.
    private init() {}
    
    /// Response Converter with default implementation to handle most common scenarios for response serialization
    /// - Parameters:
    ///   - serializer: serializer to use for response converstion.
    ///   - callback: result callback to be called after conversion.
    public static func defaultConverter<T: Codable>(serializer: Serializer, callback: @escaping ResultCallback<T>) -> HTTPResponseHandler {
        return { result -> Void in
            
            switch result {
            case .failure(let error):
                return callback(.failure(error))
            case .success(let response):
                
                if let data = response.body {
                    guard (!response.status.isError()) else {
                        
                        /// handle GetResponse 404
                        if response.status == .notFound {
                            let decodedResponse: Result<T, DecodingError> = serializer.decode(data: data)
                            switch decodedResponse {
                            case .success(let result):
                                return callback(.success(result))
                            default:
                                break;
                            }
                        }
                        
                        let decodedError: Result<ElasticsearchError, DecodingError> = serializer.decode(data: data)
                        switch decodedError {
                        case .failure(let error):
                            let converterError = ResponseConverterError(message: "Error while converting error response", error: error, response: response)
                            return callback(.failure(converterError))
                        case .success(let elasticError):
                            return callback(.failure(elasticError))
                        }
                    }
                    let decodedResponse: Result<T, DecodingError> = serializer.decode(data: data)
                    switch decodedResponse {
                    case .failure(let error):
                        let converterError = ResponseConverterError(message: "Error while converting response", error: error, response: response)
                        return callback(.failure(converterError))
                    case .success(let decoded):
                        return callback(.success(decoded))
                    }
                }<commit_msg>[chore] add trace log in default response converter<commit_after>//
//  ResponseConverters.swift
//  ElasticSwift
//
//  Created by <NAME> on 7/4/19.
//

import Foundation
import ElasticSwiftCore
import Logging

/// closure that handles `HTTPResponse`
/// - Parameters:
///    - result: result with either a success http response or Error
public typealias HTTPResponseHandler = (_ result: Result<HTTPResponse, Error>) -> Void

/// closure that handles codable result
/// - Parameters:
///    - result: result with either a success T response or Error
public typealias ResultCallback<T: Codable> = (_ result: Result<T, Error>) -> Void

/// closure that handles result of response conversion
/// - Parameters:
///     - serializer: serializer to use for response converstion
///     - callback: closure to be called after conversion.
public typealias ResponseConverter<T: Codable> = (_ serializer: Serializer, _ callback: @escaping ResultCallback<T>) -> HTTPResponseHandler


/// Classs with various response converters
public class ResponseConverters {
    
    private static let logger = Logger(label: "org.pksprojects.ElasticSwift.Serialization.ResponseConverters")
    
    /// Utility class private initializer.
    private init() {}
    
    /// Response Converter with default implementation to handle most common scenarios for response serialization
    /// - Parameters:
    ///   - serializer: serializer to use for response converstion.
    ///   - callback: result callback to be called after conversion.
    public static func defaultConverter<T: Codable>(serializer: Serializer, callback: @escaping ResultCallback<T>) -> HTTPResponseHandler {
        return { result -> Void in
            
            switch result {
            case .failure(let error):
                return callback(.failure(error))
            case .success(let response):
                
                if let data = response.body {
                    logger.trace("Converter : defaultConverter; Response body as string: \(String(data: data, encoding: .utf8) ?? "")")
                    guard (!response.status.isError()) else {
                        
                        /// handle GetResponse 404
                        if response.status == .notFound {
                            let decodedResponse: Result<T, DecodingError> = serializer.decode(data: data)
                            switch decodedResponse {
                            case .success(let result):
                                return callback(.success(result))
                            default:
                                break;
                            }
                        }
                        
                        let decodedError: Result<ElasticsearchError, DecodingError> = serializer.decode(data: data)
                        switch decodedError {
                        case .failure(let error):
                            let converterError = ResponseConverterError(message: "Error while converting error response", error: error, response: response)
                            return callback(.failure(converterError))
                        case .success(let elasticError):
                            return callback(.failure(elasticError))
                        }
                    }
                    let decodedResponse: Result<T, DecodingError> = serializer.decode(data: data)
                    switch decodedResponse {
                    case .failure(let error):
                        let converterError = ResponseConverterError(message: "Error while converting response", error: error, response: response)
                        return callback(.failure(converterError))
                    case .success(let decoded):
                        return callback(.success(decoded))
                    }
                }
{'fraction_non_alphanumeric': 0.08235294117647059, 'fraction_numerical': 0.002028397565922921, 'mean_word_length': 1.6797101449275362, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3017225', 'n_tokens_mistral': 1665, 'n_tokens_neox': 1538, 'n_words': 513}