//
//  Connector.swift
//  ScootersApp
//
//  Created by Isabela Louli on 18.03.22.
//

import Foundation

public final class Connector {
    
    private let urlSession: URLSession
    
    init(urlSession: URLSession = URLSession.shared) {
        self.urlSession = urlSession
    }
    
    public func request<T: Endpoint>(from endpoint: T, completion: @escaping (Result<T.ResponseType, NetworkingError>) -> Void) {
        
        guard let request = try? endpoint.request() else {
            completion(.failure(NetworkingError.genericError))
            return
        }
        
        let task = urlSession.dataTask(with: request) { (data, urlResponse, error) in
            
            let result: Result<T.ResponseType, NetworkingError>
            defer {
                DispatchQueue.main.async {
                    completion(result)
                }
            }
            
            guard error == nil, let statusCode = (urlResponse as? HTTPURLResponse)?.statusCode,
                                                                        (200..<299) ~= statusCode,
                                                                                    let data = data
                else {
                    result = .failure(NetworkingError.genericError)
                    return
                }
            
            do {
                let responseObject = try endpoint.decoder.decode(T.ResponseType.self, from: data)
                result = (.success(responseObject))
            } catch {
                result = (.failure(NetworkingError.genericError))
            }
        }
        
        task.resume()
    }
}

public struct NetworkingError: Error {
    let description: String
}

extension NetworkingError {
    static var genericError: NetworkingError {
        return NetworkingError(description: "Something went wrong. Check your connection and try again later")
    }
}

