/*
 * 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>: 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 var hashValue: Int {
    let prime = 31
    var result = 1
    for (key, value) in storage {
      result = prime &* result &+ key.hashValue
      result = prime &* result &+ value.hashValue
    }
    return result
  }
  
  /// 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 }
}
