/*
 * 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 TMap<Key : TSerializable & Hashable, Value : TSerializable & Hashable>: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable {
  public typealias Storage = Dictionary<Key, Value>
  public typealias Element = Storage.Element
  public typealias Index = Storage.Index
  public typealias IndexDistance = Int
  public typealias Indices = Storage.Indices
  public typealias SubSequence = Storage.SubSequence
  internal var storage = Storage()
  
  /// Mark: Be Like Dictionary
  
  public func indexForKey(_ key: Key) -> Index? {
    return storage.index(forKey: key)
  }
  
  public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
    return storage.updateValue(value, forKey: key)
  }
  
  public mutating func removeValueForKey(_ key: Key) -> Value? {
    return storage.removeValue(forKey: key)
  }
  
  public init(minimumCapacity: Int) {
    storage = Storage(minimumCapacity: minimumCapacity)
  }
  
  /// init from Dictionary<K,V>
  public init(_ dict: [Key: Value]) {
    storage = dict
  }

  /// read only access to storage if needed as Dictionary<K,V>
  public var dictionary: [Key: Value] {
    return storage
  }
  
  public subscript (key: Key) -> Value? {
    get {
      return storage[key]
    }
    set {
      storage[key] = newValue
    }
  }
  
  /// Mark: Collection
  
  public var indices: Indices {
    return storage.indices
  }
  
  public func distance(from start: Index, to end: Index) -> IndexDistance {
    return storage.distance(from: start, to: end)
  }
  
  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
    return storage.index(i, offsetBy: n)
  }
  
  public func index(_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index? {
    return storage.index(i, offsetBy: n, limitedBy: limit)
  }
  
  public subscript(position: Index) -> Element {
    return storage[position]
  }
  
  /// Mark: IndexableBase
  
  public var startIndex: Index { return storage.startIndex }
  public var endIndex: Index { return storage.endIndex }
  public func index(after i: Index) -> Index {
    return storage.index(after: i)
  }
  
  public func formIndex(after i: inout Index) {
    storage.formIndex(after: &i)
  }
  
  public subscript(bounds: Range<Index>) -> SubSequence {
    return storage[bounds]
  }
  
  /// Mark: DictionaryLiteralConvertible
  
  public init(dictionaryLiteral elements: (Key, Value)...) {
    storage = Storage()
    for (key, value) in elements {
      storage[key] = value
    }
  }

  /// Mark: Hashable

  public func hash(into hasher: inout Hasher) {
    hasher.combine(storage)
  }
  
  /// Mark: TSerializable
  
  public static var thriftType : TType { return .map }
  public init() {
    storage = Storage()
  }
   
  public static func read(from proto: TProtocol) throws -> TMap {

    let (keyType, valueType, size) = try proto.readMapBegin()
    if size > 0 {
      if keyType != Key.thriftType {
        throw TProtocolError(error: .invalidData,
                             message: "Unexpected TMap Key Type",
                             extendedError: .unexpectedType(type: keyType))
      }
      if valueType != Value.thriftType {
        throw TProtocolError(error: .invalidData,
                             message: "Unexpected TMap Value Type",
                             extendedError: .unexpectedType(type: valueType))
      }
    }

    var map = TMap()
    for _ in 0..<size {
      let key = try Key.read(from: proto)
      let value = try Value.read(from: proto)
      map.storage[key] = value
    }
    try proto.readMapEnd()
    return map
  }
  
  public func write(to proto: TProtocol) throws {
    try proto.writeMapBegin(keyType: Key.thriftType,
                            valueType: Value.thriftType, size: Int32(self.count))
    for (key, value) in self.storage {
      try Key.write(key, to: proto)
      try Value.write(value, to: proto)
    }
    try proto.writeMapEnd()
  }
}

/// Mark: CustomStringConvertible, CustomDebugStringConvertible

extension TMap : CustomStringConvertible, CustomDebugStringConvertible {
  
  public var description : String {
    return storage.description
  }
  
  public var debugDescription : String {
    return storage.debugDescription
  }
  
}

/// Mark: Equatable

public func ==<Key, Value>(lhs: TMap<Key,Value>, rhs: TMap<Key, Value>) -> Bool {
  if lhs.count != rhs.count {
    return false
  }
  return lhs.storage.elementsEqual(rhs.storage) { $0.key == $1.key && $0.value == $1.value }
}
