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

extension Set : _ObjectTypeBridgeable {
    public typealias _ObjectType = NSSet
    public func _bridgeToObjectiveC() -> _ObjectType {
        let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: count)
        
        for (idx, obj) in enumerated() {
            buffer.advanced(by: idx).initialize(to: (obj as! _ObjectBridgeable)._bridgeToAnyObject())
        }
        
        let set = NSSet(objects: buffer, count: count)
        
        buffer.deinitialize(count: count)
        buffer.deallocate(capacity: count)
        
        return set
    }
    
    public static func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Set?) {
        result = _unconditionallyBridgeFromObjectiveC(source)
    }
    
    @discardableResult
    public static func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Set?) -> Bool {
        var set = Set<Element>()
        var failedConversion = false
        
        if type(of: source) == NSSet.self || type(of: source) == NSMutableSet.self {
            source.enumerateObjects(options: []) { obj, stop in
                if let o = obj as? Element {
                    set.insert(o)
                } else {
                    // here obj must be a swift type
                    if let nsObject = _SwiftValue.store(obj) as? Element {
                        set.insert(nsObject)
                    } else {
                        failedConversion = true
                        stop.pointee = true
                    }
                }
            }
        } else if type(of: source) == _NSCFSet.self {
            let cf = source._cfObject
            let cnt = CFSetGetCount(cf)
            
            let objs = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: cnt)
            
            CFSetGetValues(cf, objs)
            
            for idx in 0..<cnt {
                let obj = unsafeBitCast(objs.advanced(by: idx), to: AnyObject.self)
                if let o = obj as? Element {
                    set.insert(o)
                } else {
                    failedConversion = true
                    break
                }
            }
            objs.deinitialize(count: cnt)
            objs.deallocate(capacity: cnt)
        }
        if !failedConversion {
            result = set
            return true
        }
        return false
    }
    
    static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Set {
        if let object = source {
            var value: Set<Element>?
            _conditionallyBridgeFromObjectiveC(object, result: &value)
            return value!
        } else {
            return Set<Element>()
        }
    }
}
