//Created  on 2019/7/23 by  LCD:https://github.com/liucaide .

/***** 模块文档 *****
 *
 */




import Foundation
import CaamDau
import SwiftyJSON
import CleanJSON


public struct NetParam {
    public static let keyPage = "pagenumber"
    public static let keySize = "pagesize"
    public static let valueSize = 10
    
    public static func pageParam(_ page:Int, param:[String:Any] = [:]) -> [String:Any] {
        var param = param
        param += [keyPage: page, keySize: valueSize]
        return param
    }
}


public struct M_BaseSuccess:CD_SwiftyJSONProtocol   {
    
    public var success:Int
    public var error:String
    public var othermsg:String
    /// - 返回的 id
    public var id:String = ""
    // ----- 如有其他的返回参数 在后面增加
    // 新增
    var code = 0
    var msg = ""
    
    /// 新接口规范字段
    public var data:JSON
    
    public enum Tags:CD_SwiftyJSONTagProtocol {
        case id
        case orderPay
    }
    
    public init(_ json: JSON, tag: CD_SwiftyJSONTagProtocol?) {
        success = json["success"].intValue
        error = json["error"].stringValue
        error = error.isEmpty ? "失败，请重试" : error
        othermsg = json["othermsg"].stringValue
        
        code = json["status"].intValue
        msg = json["msg"].stringValue
        
        id = json["id"].stringValue
        
        data = json["data"]
        
        guard let tag = tag as? Tags else {
            return
        }
        switch tag {
        case .orderPay:
            id = json["orderid"].stringValue
            othermsg = json["sn"].stringValue
        default:
            break
        }
        
    }
}


public struct M_Base<T: CD_SwiftyJSONProtocol> {
    var success:Int = 0
    var error:String = ""
    var othermsg:String = ""
    
    var data:T = T(JSON(), tag: nil)
    var datas:[T] = []
    
    // 新增
    var code = 0
    var msg = ""
    
    public enum Tags {
        /// json 在同级
        case base(_ tag:CD_SwiftyJSONTagProtocol?)
        /// json 在 key = data
        case data(_ tag:CD_SwiftyJSONTagProtocol?)
        /// json 在 key = datas
        case datas(_ tag:CD_SwiftyJSONTagProtocol?)
        /// json 在 key = key
        case keys(_ key:String, _ tag:CD_SwiftyJSONTagProtocol?)
    }
}
extension M_Base.Tags: CD_SwiftyJSONTagProtocol  {
    public var key: String {
        switch self {
        case .base:
            return ""
        case .data:
            return "data"
        case .datas:
            return "datas"
        case .keys(let key, _):
            return key
        }
    }
}

extension M_Base: CD_SwiftyJSONProtocol {
    public init(_ json: JSON, tag: CD_SwiftyJSONTagProtocol?) {
        success = json["success"].intValue
        error = json["error"].stringValue
        error = error.isEmpty ? "失败，请重试" : error
        othermsg = json["othermsg"].stringValue
        
        code = json["status"].intValue
        msg = json["msg"].stringValue
        
        guard let tag = tag as? M_Base.Tags else {
            return
        }
        switch tag {
        case .base(let t):
            data = T(json, tag: t)
        case .data(let t), .datas(let t):
            if json[tag.key].array != nil {
                datas = json[tag.key].arrayValue.compactMap{T($0, tag: t)}
            }else{
                data = T(json[tag.key], tag: t)
            }
        case .keys(_, let t):
            if json[tag.key].array != nil {
                datas = json[tag.key].arrayValue.compactMap{T($0, tag: t)}
            }else{
                data = T(json[tag.key], tag: t)
            }
        }
    }
}





//MARK:--- JSON 数据 解析 已将错误转化到 failure， mapXX 只输出成功信息----------
public extension CD_Net {
    private func datasHandler<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:(([T]) ->Void)?) {
        success = { [weak self]res in
            let json = JSON(res)
            let model = M_Base<T>(json, tag: tag)
            if model.success == 2 {
                succeed?(model.datas)
            }
            else{
                self?.failure?(CD_Net.Error(code:model.success, massage:model.error))
            }
        }
    }
    private func dataHandler<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:((T) ->Void)?) {
        success = { [weak self]res in
            let json = JSON(res)
            let model = M_Base<T>(json, tag: tag)
            if model.success == 2 {
                succeed?(model.data)
            }
            else{
                self?.failure?(CD_Net.Error(code:model.success, massage:model.error))
            }
        }
    }
    /// 返回json -> datas key = 其他字段 的模型数组
    @discardableResult
    func mapOthers<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:(([T]) ->Void)?) -> Self {
        datasHandler(t, tag: tag, succeed: succeed)
        return self
    }
    /// 返回json -> key = 其他字段 的模型数组
    @discardableResult
    func mapOther<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:((T) ->Void)?) -> Self {
        dataHandler(t, tag: tag, succeed: succeed)
        return self
    }
    
    /// 旧接口：返回json -> key = datas 的模型数组
    @discardableResult
    func mapDatas<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:(([T]) ->Void)?) -> Self {
        datasHandler(t, tag: M_Base<T>.Tags.datas(tag), succeed: succeed)
        return self
    }
    
    /// 旧接口：返回json -> key = data 的模型
    @discardableResult
    func mapData<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:((T) ->Void)?) -> Self {
        dataHandler(t, tag: M_Base<T>.Tags.data(tag), succeed: succeed)
        return self
    }
    
    /// 返回json 的模型
    @discardableResult
    func mapBase<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:((T) ->Void)?) -> Self {
        dataHandler(t, tag: M_Base<T>.Tags.base(tag), succeed: succeed)
        return self
    }
    
    /// 返回成功信息
    @discardableResult
    func mapSucceed(_ succeed:((M_BaseSuccess) ->Void)? = nil, tag:CD_SwiftyJSONTagProtocol? = nil) -> Self {
        dataHandler(M_BaseSuccess.self, tag: M_Base<M_BaseSuccess>.Tags.base(tag), succeed: succeed)
        return self
    }
    
    /// 返回成功信息, JSON 原数据
    @discardableResult
    func mapJSON(_ succeed:((JSON) ->Void)? = nil) -> Self {
        success = { [weak self]res in
            let json = JSON(res)
            let m = M_BaseSuccess(json, tag: nil)
            if m.success == 2 {
                succeed?(json)
            }else{
                self?.failure?(CD_Net.Error(code:m.success, massage:m.error))
            }
        }
        return self
    }
    
    /// 返回模型
    @discardableResult
    func mapModel<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:((T) ->Void)?) -> Self {
        dataHandler(t, tag: M_Base<T>.Tags.data(tag), succeed: succeed)
        return self
    }
    
    /// 返回模型数组
    @discardableResult
    func mapModels<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil, succeed:(([T]) ->Void)?) -> Self {
        datasHandler(t, tag: M_Base<T>.Tags.data(tag), succeed: succeed)
        return self
    }
}

//MARK:--- 从 Data 转模型 用于本地缓存转模型 ----------
public extension Data {
    private func datasHandler<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> [T] {
        let json = JSON(self)
        let model = M_Base<T>(json, tag: tag)
        if model.success == 2 {
            return model.datas
        }
        else{
            return []
        }
    }
    private func dataHandler<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> T? {
        let json = JSON(self)
        let model = M_Base<T>(json, tag: tag)
        if model.success == 2 {
            return model.data
        }
        else{
            return nil
        }
    }
    
    /// 旧接口：返回json -> key = datas 的模型数组
    func mapDatas<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> [T] {
        return datasHandler(t, tag: M_Base<T>.Tags.datas(tag))
    }
    /// 旧接口：返回json -> key = data 的模型
    func mapData<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> T? {
        return dataHandler(t, tag: M_Base<T>.Tags.data(tag))
    }
    /// 返回json 的模型
    func mapBase<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> T? {
        return dataHandler(t, tag: M_Base<T>.Tags.base(tag))
    }
    /// 返回json 的模型
    func mapOthers<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> [T] {
        return datasHandler(t, tag: tag)
    }
    /// 返回json 的模型
    func mapOther<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> T? {
        return dataHandler(t, tag:tag)
    }
    
    /// 返回模型数组
    func mapModels<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> [T] {
        return datasHandler(t, tag: M_Base<T>.Tags.data(tag))
    }
    /// 返回模型
    func mapModel<T:CD_SwiftyJSONProtocol>(_ t:T.Type, tag:CD_SwiftyJSONTagProtocol? = nil) -> T? {
        return dataHandler(t, tag: M_Base<T>.Tags.data(tag))
    }
}
