// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//


import CoreFoundation

internal final class _NSCFDictionary : NSMutableDictionary {
    deinit {
        _CFDeinit(self)
        _CFZeroUnsafeIvars(&_storage)
    }
    
    required init() {
        fatalError()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }

    required init(objects: UnsafePointer<AnyObject>, forKeys keys: UnsafePointer<NSObject>, count cnt: Int) {
        fatalError()
    }
    
    required convenience init(dictionaryLiteral elements: (NSObject, AnyObject)...) {
        fatalError()
    }
    
    override var count: Int {
        return CFDictionaryGetCount(unsafeBitCast(self, to: CFDictionary.self))
    }
    
    override func objectForKey(aKey: AnyObject) -> AnyObject? {
        let value = CFDictionaryGetValue(_cfObject, unsafeBitCast(aKey, to: UnsafePointer<Void>.self))
        if value != nil {
            return unsafeBitCast(value, to: AnyObject.self)
        } else {
            return nil
        }
    }
    
    // This doesn't feel like a particularly efficient generator of CFDictionary keys, but it works for now. We should probably put a function into CF that allows us to simply iterate the keys directly from the underlying CF storage.
    private struct _NSCFKeyGenerator : IteratorProtocol {
        var keyArray : [NSObject] = []
        var index : Int = 0
        let count : Int
        mutating func next() -> AnyObject? {
            if index == count {
                return nil
            } else {
                let item = keyArray[index]
                index += 1
                return item
            }
        }
        
        init(_ dict : _NSCFDictionary) {
            let cf = dict._cfObject
            count = CFDictionaryGetCount(cf)
            
            let keys = UnsafeMutablePointer<UnsafePointer<Void>>(allocatingCapacity: count)            
            CFDictionaryGetKeysAndValues(cf, keys, nil)
            
            for idx in 0..<count {
                let key = unsafeBitCast(keys.advanced(by: idx).pointee, to: NSObject.self)
                keyArray.append(key)
            }
            keys.deinitialize()
            keys.deallocateCapacity(count)
        }
    }

    override func keyEnumerator() -> NSEnumerator {
        return NSGeneratorEnumerator(_NSCFKeyGenerator(self))
    }

    override func removeObjectForKey(aKey: AnyObject) {
        CFDictionaryRemoveValue(_cfMutableObject, unsafeBitCast(aKey, to: UnsafePointer<Void>.self))
    }
    
    override func setObject(anObject: AnyObject, forKey aKey: NSObject) {
        CFDictionarySetValue(_cfMutableObject, unsafeBitCast(aKey, to: UnsafePointer<Void>.self), unsafeBitCast(anObject, to: UnsafePointer<Void>.self))
    }
    
    override var classForCoder: AnyClass {
        return NSMutableDictionary.self
    }
}

internal func _CFSwiftDictionaryGetCount(dictionary: AnyObject) -> CFIndex {
    return (dictionary as! NSDictionary).count
}

internal func _CFSwiftDictionaryGetCountOfKey(dictionary: AnyObject, key: AnyObject) -> CFIndex {
    if _CFSwiftDictionaryContainsKey(dictionary, key: key) {
        return 1
    } else {
        return 0
    }
}

internal func _CFSwiftDictionaryContainsKey(dictionary: AnyObject, key: AnyObject) -> Bool {
    return (dictionary as! NSDictionary).objectForKey(key) != nil
}

//(AnyObject, AnyObject) -> Unmanaged<AnyObject>
internal func _CFSwiftDictionaryGetValue(dictionary: AnyObject, key: AnyObject) -> Unmanaged<AnyObject>? {
    if let obj = (dictionary as! NSDictionary).objectForKey(key) {
        return Unmanaged<AnyObject>.passUnretained(obj)
    } else {
        return nil
    }
}

internal func _CFSwiftDictionaryGetValueIfPresent(dictionary: AnyObject, key: AnyObject, value: UnsafeMutablePointer<Unmanaged<AnyObject>?>) -> Bool {
    if let val = _CFSwiftDictionaryGetValue(dictionary, key: key) {
        value.pointee = val
        return true
    } else {
        value.pointee = nil
        return false
    }
}

internal func _CFSwiftDictionaryGetCountOfValue(dictionary: AnyObject, value: AnyObject) -> CFIndex {
    if _CFSwiftDictionaryContainsValue(dictionary, value: value) {
        return 1
    } else {
        return 0
    }
}

internal func _CFSwiftDictionaryContainsValue(dictionary: AnyObject, value: AnyObject) -> Bool {
    NSUnimplemented()
}

internal func _CFSwiftDictionaryGetValuesAndKeys(dictionary: AnyObject, valuebuf: UnsafeMutablePointer<Unmanaged<AnyObject>?>, keybuf: UnsafeMutablePointer<Unmanaged<AnyObject>?>) {
    var idx = 0
    if valuebuf == nil && keybuf == nil {
        return
    }
    (dictionary as! NSDictionary).enumerateKeysAndObjectsUsingBlock { key, value, _ in
	if valuebuf != nil {
	    valuebuf[idx] = Unmanaged<AnyObject>.passUnretained(value)
	}
	if keybuf != nil {
	    keybuf[idx] = Unmanaged<AnyObject>.passUnretained(key)
	}
        idx += 1
    }
}

internal func _CFSwiftDictionaryApplyFunction(dictionary: AnyObject, applier: @convention(c) (AnyObject, AnyObject, UnsafeMutablePointer<Void>) -> Void, context: UnsafeMutablePointer<Void>) {
    (dictionary as! NSDictionary).enumerateKeysAndObjectsUsingBlock { key, value, _ in
        applier(key, value, context)
    }
}

internal func _CFSwiftDictionaryAddValue(dictionary: AnyObject, key: AnyObject, value: AnyObject) {
    (dictionary as! NSMutableDictionary).setObject(value, forKey: key as! NSObject)
}

internal func _CFSwiftDictionaryReplaceValue(dictionary:  AnyObject, key: AnyObject, value: AnyObject) {
    (dictionary as! NSMutableDictionary).setObject(value, forKey: key as! NSObject)
}

internal func _CFSwiftDictionarySetValue(dictionary:  AnyObject, key: AnyObject, value: AnyObject) {
    (dictionary as! NSMutableDictionary).setObject(value, forKey: key as! NSObject)
}

internal func _CFSwiftDictionaryRemoveValue(dictionary:  AnyObject, key: AnyObject) {
    (dictionary as! NSMutableDictionary).removeObjectForKey(key)
}

internal func _CFSwiftDictionaryRemoveAllValues(dictionary: AnyObject) {
    (dictionary as! NSMutableDictionary).removeAllObjects()
}
