/*
 * 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.
 */


/// Protocol for Generated Structs to conform to
/// Dictionary maps field names to internal IDs and uses Reflection
/// to iterate through all fields.  
/// `writeFieldValue(_:name:type:id:)` calls `TSerializable.write(to:)` internally
/// giving a nice recursive behavior for nested TStructs, TLists, TMaps, and TSets
public protocol TStruct : TSerializable {
  static var fieldIds: [String: Int32] { get }
  static var structName: String { get }
}

public extension TStruct {
  static var fieldIds: [String: (id: Int32, type: TType)] { return [:] }
  static var thriftType: TType { return .struct }
  
  func write(to proto: TProtocol) throws {
    // Write struct name first
    try proto.writeStructBegin(name: Self.structName)
    
    try self.forEach { name, value, id in
      // Write to protocol
      try proto.writeFieldValue(value, name: name,
                                type: value.thriftType, id: id)
    }
    try proto.writeFieldStop()
    try proto.writeStructEnd()
  }
  
  /// Provides a block for handling each (available) thrift property using reflection
  /// Caveat: Skips over optional values
  
  
  /// Provides a block for handling each (available) thrift property using reflection
  ///
  /// - parameter block: block for handling property
  ///
  /// - throws: rethrows any Error thrown in block
  private func forEach(_ block: (_ name: String, _ value: TSerializable, _ id: Int32) throws -> Void) rethrows {
    // Mirror the object, getting (name: String?, value: Any) for every property
    let mirror = Mirror(reflecting: self)
    
    // Iterate through all children, ignore empty property names
    for (propName, propValue) in mirror.children {
      guard let propName = propName else { continue }

      if let tval = unwrap(any: propValue) as? TSerializable, let id = Self.fieldIds[propName] {
        try block(propName, tval, id)
      }
    }
  }
  
  
  /// Any can mysteriously be an Optional<Any> at the same time,
  /// this checks and always returns Optional<Any> without double wrapping
  /// we then try to bind value as TSerializable to ignore any extension properties
  /// and the like and verify the property exists and grab the Thrift
  /// property ID at the same time
  ///
  /// - parameter any: Any instance to attempt to unwrap
  ///
  /// - returns: Unwrapped Any as Optional<Any>
  private func unwrap(any: Any) -> Any? {
    let mi = Mirror(reflecting: any)
    
    if mi.displayStyle != .optional { return any }
    if mi.children.count == 0 { return nil }
    
    let (_, some) = mi.children.first!
    return some
  }
}

