/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/


public struct TApplicationError : TError {
  public enum Code : TErrorCode {
    case unknown
    case unknownMethod(methodName: String?)
    case invalidMessageType
    case wrongMethodName(methodName: String?)
    case badSequenceId
    case missingResult(methodName: String?)
    case internalError
    case protocolError
    case invalidTransform
    case invalidProtocol
    case unsupportedClientType
    
    
    /// Initialize a TApplicationError with a Thrift error code
    /// Normally this would be achieved with RawRepresentable however
    /// by doing this we can allow for associated properties on enum cases for
    /// case specific context data in a Swifty, type-safe manner.
    ///
    /// - parameter thriftErrorCode: Integer TApplicationError(exception) error code.  
    ///                              Default to 0 (.unknown)
    public init(thriftErrorCode: Int) {
      switch thriftErrorCode {
      case 1:  self = .unknownMethod(methodName: nil)
      case 2:  self = .invalidMessageType
      case 3:  self = .wrongMethodName(methodName: nil)
      case 4:  self = .badSequenceId
      case 5:  self = .missingResult(methodName: nil)
      case 6:  self = .internalError
      case 7:  self = .protocolError
      case 8:  self = .invalidProtocol
      case 9:  self = .invalidTransform
      case 10: self = .unsupportedClientType
      default: self = .unknown
      }
    }
    public var thriftErrorCode: Int {
      switch self {
      case .unknown:                return 0
      case .unknownMethod:          return 1
      case .invalidMessageType:     return 2
      case .wrongMethodName:        return 3
      case .badSequenceId:          return 4
      case .missingResult:          return 5
      case .internalError:          return 6
      case .protocolError:          return 7
      case .invalidProtocol:        return 8
      case .invalidTransform:       return 9
      case .unsupportedClientType:  return 10
      }
    }
    
    public var description: String {
      /// Output "for #methodName" if method is not nil else empty
      let methodUnwrap: (String?) -> String =  { method in
        return "\(method == nil ? "" : " for \(method ?? "")")"
      }
      switch self {
      case .unknown:                      return "Unknown TApplicationError"
      case .unknownMethod(let method):    return "Unknown Method\(methodUnwrap(method))"
      case .invalidMessageType:           return "Invalid Message Type"
      case .wrongMethodName(let method):  return "Wrong Method Name\(methodUnwrap(method))"
      case .badSequenceId:                return "Bad Sequence ID"
      case .missingResult(let method):    return "Missing Result\(methodUnwrap(method))"
      case .internalError:                return "Internal Error"
      case .protocolError:                return "Protocol Error"
      case .invalidProtocol:              return "Invalid Protocol"
      case .invalidTransform:             return "Invalid Transform"
      case .unsupportedClientType:        return "Unsupported Client Type"
      }
    }
  }

  public init() { }
  
  public init(thriftErrorCode code: Int, message: String? = nil) {
    self.error = Code(thriftErrorCode: code)
    self.message = message
  }
  
  public var error: Code = .unknown
  public var message: String? = nil
  public static var defaultCase: Code { return .unknown }
}

extension TApplicationError : TSerializable {
  public static var thriftType: TType { return .struct }
  
  public static func read(from proto: TProtocol) throws -> TApplicationError {
    var errorCode: Int = 0
    var message: String? = nil
    _ = try proto.readStructBegin()
    fields: while true {
      let (_, fieldType, fieldID) = try proto.readFieldBegin()
      
      switch (fieldID, fieldType) {
      case (_, .stop):
        break fields
      case (1, .string):
        message = try proto.read()
      case (2, .i32):
        errorCode = Int(try proto.read() as Int32)
      
      case let (_, unknownType):
        try proto.skip(type: unknownType)
      }
      
      try proto.readFieldEnd()
    }
    try proto.readStructEnd()
    return TApplicationError(thriftErrorCode: errorCode, message: message)
  }

  public func write(to proto: TProtocol) throws {
    try proto.writeStructBegin(name: "TApplicationException")
    
    try proto.writeFieldBegin(name: "message", type: .string, fieldID: 1)
    try proto.write(message ?? "")
    try proto.writeFieldEnd()
    
    try proto.writeFieldBegin(name: "type", type: .i32, fieldID: 2)
    let val = Int32(error.thriftErrorCode)
    try proto.write(val)
    try proto.writeFieldEnd()
    try proto.writeFieldStop()
    try proto.writeStructEnd()
  }
}

extension TApplicationError: Hashable {
  public func hash(into hasher: inout Hasher) {
    hasher.combine(error.thriftErrorCode)
    hasher.combine(message)
  }
}

public func ==(lhs: TApplicationError, rhs: TApplicationError) -> Bool {
  return lhs.error.thriftErrorCode == rhs.error.thriftErrorCode && lhs.message == rhs.message
}
