// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 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 _NSCFSet : NSMutableSet {
    deinit {
        _CFDeinit(self)
        _CFZeroUnsafeIvars(&_storage)
    }
    
    required init() {
        fatalError()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }

    required init(capacity numItems: Int) {
        fatalError()
    }
    
    override var classForCoder: AnyClass {
        return NSMutableSet.self
    }
    
    override var count: Int {
        return CFSetGetCount(_cfObject)
    }
    
    override func member(_ object: Any) -> Any? {
        
        guard let value = CFSetGetValue(_cfObject, unsafeBitCast(_SwiftValue.store(object), to: UnsafeRawPointer.self)) else {
            return nil
        }
        return _SwiftValue.fetch(unsafeBitCast(value, to: AnyObject.self))
        
    }
    
    override func objectEnumerator() -> NSEnumerator {
        
        var objArray: [AnyObject] = []
        let cf = _cfObject
        let count = CFSetGetCount(cf)
        
        let objects = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: count)
        CFSetGetValues(cf, objects)
        
        for idx in 0..<count {
            let obj = unsafeBitCast(objects.advanced(by: idx).pointee!, to: AnyObject.self)
            objArray.append(obj)
        }
        objects.deinitialize()
        objects.deallocate(capacity: count)
        
        return NSGeneratorEnumerator(objArray.makeIterator())
        
    }
    
    override func add(_ object: Any) {
        CFSetAddValue(_cfMutableObject, unsafeBitCast(_SwiftValue.store(object), to: UnsafeRawPointer.self))
    }
    
    override func remove(_ object: Any) {
        CFSetRemoveValue(_cfMutableObject, unsafeBitCast(_SwiftValue.store(object), to: UnsafeRawPointer.self))
    }
    
}

internal func _CFSwiftSetGetCount(_ set: AnyObject) -> CFIndex {
    return (set as! NSSet).count
}

internal func _CFSwiftSetGetCountOfValue(_ set: AnyObject, value: AnyObject) -> CFIndex {
    if _CFSwiftSetContainsValue(set, value: value) {
        return 1
    } else {
        return 0
    }
}

internal func _CFSwiftSetContainsValue(_ set: AnyObject, value: AnyObject) -> Bool {
    return _CFSwiftSetGetValue(set, value: value) != nil
}

internal func _CFSwiftSetGetValues(_ set: AnyObject, _ values: UnsafeMutablePointer<Unmanaged<AnyObject>?>?) {
    
    var idx = 0
    if values == nil {
        return
    }
    
    let set = set as! NSSet
    if type(of: set) === NSSet.self || type(of: set) === NSMutableSet.self {
        for obj in set._storage {
            values?[idx] = Unmanaged<AnyObject>.passUnretained(obj)
            idx += 1
        }
    } else {
        set.enumerateObjects( { v, _ in
            let value = _SwiftValue.store(v)
            values?[idx] = Unmanaged<AnyObject>.passUnretained(value)
            set._storage.update(with: value)
            idx += 1
        })
    }
}

internal func _CFSwiftSetGetValue(_ set: AnyObject, value: AnyObject) -> Unmanaged<AnyObject>? {
    let set = set as! NSSet
    if type(of: set) === NSSet.self || type(of: set) === NSMutableSet.self {
        if let idx = set._storage.index(of: value as! NSObject){
            return Unmanaged<AnyObject>.passUnretained(set._storage[idx])
        }
        
    } else {
        let v = _SwiftValue.store(set.member(value))
        if let obj = v {
            set._storage.update(with: obj)
            return Unmanaged<AnyObject>.passUnretained(obj)
        }
    }
    return nil
}

internal func _CFSwiftSetGetValueIfPresent(_ set: AnyObject, object: AnyObject, value: UnsafeMutablePointer<Unmanaged<AnyObject>?>?) -> Bool {
    if let val = _CFSwiftSetGetValue(set, value: object) {
        value?.pointee = val
        return true
    } else {
        value?.pointee = nil
        return false
    }
}

internal func _CFSwiftSetApplyFunction(_ set: AnyObject, applier: @convention(c) (AnyObject, UnsafeMutableRawPointer) -> Void, context: UnsafeMutableRawPointer) {
    (set as! NSSet).enumerateObjects({ value, _ in
        applier(_SwiftValue.store(value), context)
    })
}

internal func _CFSwiftSetAddValue(_ set: AnyObject, value: AnyObject) {
    (set as! NSMutableSet).add(value)
}

internal func _CFSwiftSetReplaceValue(_ set:  AnyObject, value: AnyObject) {
    let set = set as! NSMutableSet
    if (set.contains(value)){
        set.remove(value)
        set.add(value)
    }
}

internal func _CFSwiftSetSetValue(_ set:  AnyObject, value: AnyObject) {
    let set = set as! NSMutableSet
    set.remove(value)
    set.add(value)
}

internal func _CFSwiftSetRemoveValue(_ set:  AnyObject, value: AnyObject) {
    (set as! NSMutableSet).remove(value)
}

internal func _CFSwiftSetRemoveAllValues(_ set: AnyObject) {
    (set as! NSMutableSet).removeAllObjects()
}

internal func _CFSwiftSetCreateCopy(_ set: AnyObject) -> Unmanaged<AnyObject> {
    return Unmanaged<AnyObject>.passRetained((set as! NSSet).copy() as! NSObject)
}
