//
//  SWNetRequest.swift
//  LiteraryHeaven
//
//  Created by SanW on 2017/8/2.
//  Copyright © 2017年 ONON. All rights reserved.
//

import Alamofire
import UIKit

// 默认超时时间
public let timeoutInterval: TimeInterval = 30

// MARK: - 错误

/// 错误
public struct PQError: Error {
    public var msg: String? // 提示信息
    public var code: Int // 错误吗

    init(msg: String?, code: Int = 0) {
        self.msg = msg
        self.code = code
    }

    public var localizedDescription: String {
        return msg ?? ""
    }
}

// MARK: - 网络请求

/// 网络请求
public class SWNetRequest: NSObject {
    static let sessionManager: Alamofire.SessionManager = {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = timeoutInterval
        return Alamofire.SessionManager(configuration: configuration)
    }()

    static let reTrySessionManager: Alamofire.SessionManager = {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 5
        return Alamofire.SessionManager(configuration: configuration)
    }()

    /// 回调方法
    public typealias completeHander = (_ responseobject: Any?, _ extData: [String: Any]?, _ error: PQError?, _ timeline: Timeline) -> Void
    /// get请求
    public class func getRequestData(url: String, parames: [String: Any]?, encoding: ParameterEncoding = URLEncoding.default, timeoutInterval: TimeInterval = timeoutInterval, response: @escaping completeHander) {
        requestData(method: .get, encoding: encoding, url: url, parames: parames, timeoutInterval: timeoutInterval) { responseObject, extData, error, timeline in
            response(responseObject, extData, error, timeline)
        }
    }

    /// post请求
    public class func postRequestData(url: String, parames: [String: Any]?, encoding: ParameterEncoding = URLEncoding.default, timeoutInterval: TimeInterval = timeoutInterval, response: @escaping completeHander) {
        requestData(method: .post, encoding: encoding, url: url, parames: parames, timeoutInterval: timeoutInterval) { responseObject, extData, error, timeline in
            response(responseObject, extData, error, timeline)
        }
    }

    /// 发送head请求
    /// - Parameter url: <#url description#>
    /// - Returns: <#description#>
    class public func headRequestData(url: String, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
        BFLog(message: "发起head请求 = \(url)")
        if !isValidURL(url: url) {
            completionHandler(nil, nil, PQError(msg: "url错误", code: 1001))
            return
        }
        // http://www.mxfjx.com/uploadfiles/2014/4/小鸡%20鸡蛋%20蛋生鸡%20鸡生蛋_conew1.gif
        url.urlEncoded()
        let reqUrl = URL(string: url)!
        var request = URLRequest(url: reqUrl)
        request.timeoutInterval = 1 // 设置超时1s
        request.httpMethod = "HEAD"
        let session = URLSession.shared
        let headTask = session.dataTask(with: request) { data, response, error in
            completionHandler(data, response, error)
            BFLog(message: "head请求返回 = \(url),code = \((response as? HTTPURLResponse)?.statusCode ?? 0),response = \(String(describing: response))")
        }
        headTask.resume()
    }

    /// put请求
    public class func putRequestData(url: String, parames: [String: Any]?, encoding: ParameterEncoding = URLEncoding.default, timeoutInterval: TimeInterval = timeoutInterval, response: @escaping completeHander) {
        requestData(method: .put, encoding: encoding, url: url, parames: parames, timeoutInterval: timeoutInterval) { responseObject, extData, error, timeline in
            response(responseObject, extData, error, timeline)
        }
    }

    /// delete请求
    public class func deleteRequestData(url: String, parames: [String: Any]?, encoding: ParameterEncoding = URLEncoding.default, timeoutInterval: TimeInterval = timeoutInterval, response: @escaping completeHander) {
        requestData(method: .delete, encoding: encoding, url: url, parames: parames, timeoutInterval: timeoutInterval) { responseObject, extData, error, timeline in
            response(responseObject, extData, error, timeline)
        }
    }

    /// 网络请求
    fileprivate class func requestData(method: HTTPMethod, encoding: ParameterEncoding, url: String, parames: [String: Any]?, timeoutInterval _: TimeInterval = timeoutInterval, response: @escaping completeHander) {
        var requestParams: [String: Any] = Dictionary<String, Any>.init()
        if encoding is JSONEncoding {
            requestParams["baseInfo"] = commonParams()
            requestParams["params"] = parames
        } else {
            requestParams = commonParams()
            if parames != nil, parames?.count ?? 0 > 0 {
                if parames?.keys.contains("abInfoData") ?? false, "\(parames?["abInfoData"] ?? "")".count > 0, "\(parames?["abInfoData"] ?? "")" != "{}" {
                    requestParams.removeValue(forKey: "abInfoData")
                }
                for (key, value) in parames!.reversed() {
                    requestParams[key] = value
                }
            }
        }
        BFLog(message: "发起请求：\(url),params：\(requestParams)")
        (timeoutInterval <= 5 ? reTrySessionManager : sessionManager).request(url, method: method, parameters: requestParams, encoding: encoding, headers: nil).responseJSON { jsonResponse in
            BFLog(message: "jsonResponse = \(jsonResponse.timeline)")
            /// 返回值
            if jsonResponse.result.isSuccess {
                let respondDict: [String: Any] = try! JSONSerialization.jsonObject(with: jsonResponse.data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: Any]
                BFLog(message: "请求成功：\(url),respond:\(respondDict)")
                if respondDict.keys.contains("code") && "\(respondDict["code"] ?? "")" == "0" && respondDict.keys.contains("data") {
                    let extData = respondDict["extData"] as? [String: Any]
                    if extData != nil && (extData?.keys.contains("abInfoData") ?? false) {
//                        PQSingletoMemoryUtil.shared.parasABinfoData(abInfo: extData?["abInfoData"] as? String)
                    }
                    response(respondDict["data"], extData, nil, jsonResponse.timeline)
                } else if (respondDict.keys.contains("msg") && "\(respondDict["msg"] ?? "")".count > 0) || (respondDict.keys.contains("message") && "\(respondDict["message"] ?? "")".count > 0) {
                    response(respondDict["data"], nil, PQError(msg: "\(respondDict["msg"] ?? "")", code: Int("\(respondDict["code"] ?? "")") ?? 10001), jsonResponse.timeline)
                } else {
                    response(nil, nil, PQError(msg: jsonResponse.result.error?.localizedDescription, code: 10001), jsonResponse.timeline)
                }
            } else {
                BFLog(message: "请求失败：\(url),error:\(jsonResponse.result.error?.localizedDescription ?? "")")
                let code: Int? = (jsonResponse.result.error as NSError?)?.code
                response(nil, nil, PQError(msg: (code == -1009 || code == -1001) ? "网络不可用" : jsonResponse.result.error?.localizedDescription, code: code ?? 10001), jsonResponse.timeline)
            }
        }
    }

    /// 取消网络请求
    /// - Parameter url: 某一个地址，空则取消所有
    /// - Returns: <#description#>
    public class func cancelTask(url: String?) {
        sessionManager.session.getAllTasks(completionHandler: { tasks in
            tasks.forEach { task in
                if task.currentRequest?.url?.absoluteString == url {
                    task.cancel()
                }
            }
        })
    }
}
