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

open class NSSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding {
    private let _cfinfo = _CFInfo(typeID: CFSetGetTypeID())
    internal var _storage: Set<NSObject>
    
    open var count: Int {
        guard type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self || type(of: self) === NSCountedSet.self else {
            NSRequiresConcreteImplementation()
        }
        return _storage.count
    }
    
    open func member(_ object: Any) -> Any? {
        guard type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self || type(of: self) === NSCountedSet.self else {
            NSRequiresConcreteImplementation()
        }
        let value = _SwiftValue.store(object)
        guard let idx = _storage.index(of: value) else { return nil }
        return _storage[idx]
    }
    
    open func objectEnumerator() -> NSEnumerator {
        guard type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self || type(of: self) === NSCountedSet.self else {
            NSRequiresConcreteImplementation()
        }
        return NSGeneratorEnumerator(_storage.map { _SwiftValue.fetch(nonOptional: $0) }.makeIterator())
    }

    public convenience override init() {
        self.init(objects: [], count: 0)
    }
    
    public init(objects: UnsafePointer<AnyObject>!, count cnt: Int) {
        _storage = Set(minimumCapacity: cnt)
        super.init()
        let buffer = UnsafeBufferPointer(start: objects, count: cnt)
        for obj in buffer {
            _storage.insert(obj as! NSObject)
        }
    }
    
    public required convenience init?(coder aDecoder: NSCoder) {
        guard aDecoder.allowsKeyedCoding else {
            preconditionFailure("Unkeyed coding is unsupported.")
        }
        if type(of: aDecoder) == NSKeyedUnarchiver.self || aDecoder.containsValue(forKey: "NS.objects") {
            let objects = aDecoder._decodeArrayOfObjectsForKey("NS.objects")
            self.init(array: objects as! [NSObject])
        } else {
            var objects = [AnyObject]()
            var count = 0
            while let object = aDecoder.decodeObject(forKey: "NS.object.\(count)") {
                objects.append(object as! NSObject)
                count += 1
            }
            self.init(array: objects)
        }
    }
    
    open func encode(with aCoder: NSCoder) {
        // The encoding of a NSSet is identical to the encoding of an NSArray of its contents
        self.allObjects._nsObject.encode(with: aCoder)
    }
    
    open override func copy() -> Any {
        return copy(with: nil)
    }
    
    open func copy(with zone: NSZone? = nil) -> Any {
        if type(of: self) === NSSet.self {
            // return self for immutable type
            return self
        } else if type(of: self) === NSMutableSet.self {
            let set = NSSet()
            set._storage = self._storage
            return set
        }
        return NSSet(array: self.allObjects)
    }
    
    open override func mutableCopy() -> Any {
        return mutableCopy(with: nil)
    }

    open func mutableCopy(with zone: NSZone? = nil) -> Any {
        if type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self {
            // always create and return an NSMutableSet
            let mutableSet = NSMutableSet()
            mutableSet._storage = self._storage
            return mutableSet
        }
        return NSMutableSet(array: self.allObjects)
    }

    public static var supportsSecureCoding: Bool {
        return true
    }
    
    open func description(withLocale locale: Locale?) -> String { NSUnimplemented() }
    
    override open var _cfTypeID: CFTypeID {
        return CFSetGetTypeID()
    }

    open override func isEqual(_ value: Any?) -> Bool {
        if let other = value as? Set<AnyHashable> {
            return isEqual(to: other)
        } else if let other = value as? NSSet {
            return isEqual(to: Set._unconditionallyBridgeFromObjectiveC(other))
        }
        return false
    }

    open override var hash: Int {
        return self.count
    }

    public convenience init(array: [Any]) {
        let buffer = UnsafeMutablePointer<AnyObject>.allocate(capacity: array.count)
        for (idx, element) in array.enumerated() {
            buffer.advanced(by: idx).initialize(to: _SwiftValue.store(element))
        }
        self.init(objects: buffer, count: array.count)
        buffer.deinitialize(count: array.count)
        buffer.deallocate(capacity: array.count)
    }

    public convenience init(set: Set<AnyHashable>) {
        self.init(set: set, copyItems: false)
    }

    public convenience init(set: Set<AnyHashable>, copyItems flag: Bool) {
        if flag {
            self.init(array: set.map {
                if let item = $0 as? NSObject {
                    return item.copy()
                } else {
                    return $0
                }
            })
        } else {
            self.init(array: set.map { $0 })
        }
    }
}

extension NSSet {
    
    public convenience init(object: Any) {
        self.init(array: [object])
    }
}

extension NSSet {
    
    open var allObjects: [Any] {
        if type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self {
            return _storage.map { _SwiftValue.fetch(nonOptional: $0) }
        } else {
            let enumerator = objectEnumerator()
            var items = [Any]()
            while let val = enumerator.nextObject() {
                items.append(val)
            }
            return items
        }
    }
    
    open func anyObject() -> Any? {
        return objectEnumerator().nextObject()
    }
    
    open func contains(_ anObject: Any) -> Bool {
        return member(anObject) != nil
    }
    
    open func intersects(_ otherSet: Set<AnyHashable>) -> Bool {
        if count < otherSet.count {
            for item in self {
                if otherSet.contains(item as! AnyHashable) {
                    return true
                }
            }
            return false
        } else {
            return otherSet.contains { obj in contains(obj) }
        }
    }
    
    open func isEqual(to otherSet: Set<AnyHashable>) -> Bool {
        return count == otherSet.count && isSubset(of: otherSet)
    }
    
    open func isSubset(of otherSet: Set<AnyHashable>) -> Bool {
        // `true` if we don't contain any object that `otherSet` doesn't contain.
        for item in self {
            if !otherSet.contains(item as! AnyHashable) {
                return false
            }
        }
        return true
    }

    open func adding(_ anObject: Any) -> Set<AnyHashable> {
        return self.addingObjects(from: [anObject])
    }
    
    open func addingObjects(from other: Set<AnyHashable>) -> Set<AnyHashable> {
        var result = Set<AnyHashable>(minimumCapacity: Swift.max(count, other.count))
        if type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self {
            result.formUnion(_storage.map { _SwiftValue.fetch(nonOptional: $0) as! AnyHashable })
        } else {
            for case let obj as NSObject in self {
                _ = result.insert(obj)
            }
        }
        return result.union(other)
    }
    
    open func addingObjects(from other: [Any]) -> Set<AnyHashable> {
        var result = Set<AnyHashable>(minimumCapacity: count)
        if type(of: self) === NSSet.self || type(of: self) === NSMutableSet.self {
            result.formUnion(_storage.map { _SwiftValue.fetch(nonOptional: $0) as! AnyHashable })
        } else {
            for case let obj as AnyHashable in self {
                result.insert(obj)
            }
        }
        for case let obj as AnyHashable in other {
            result.insert(obj)
        }
        return result
    }

    open func enumerateObjects(_ block: (Any, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) {
        enumerateObjects(options: [], using: block)
    }
    
    open func enumerateObjects(options opts: NSEnumerationOptions = [], using block: (Any, UnsafeMutablePointer<ObjCBool>) -> Swift.Void) {
        var stop : ObjCBool = false
        for obj in self {
            withUnsafeMutablePointer(to: &stop) { stop in
                block(obj, stop)
            }
            if stop {
                break
            }
        }
    }

    open func objects(passingTest predicate: (Any, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Set<AnyHashable> {
        return objects(options: [], passingTest: predicate)
    }
    
    open func objects(options opts: NSEnumerationOptions = [], passingTest predicate: (Any, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Set<AnyHashable> {
        var result = Set<AnyHashable>()
        enumerateObjects(options: opts) { obj, stopp in
            if predicate(obj, stopp) {
                result.insert(obj as! AnyHashable)
            }
        }
        return result
    }
}

extension NSSet : _CFBridgeable, _SwiftBridgeable {
    internal var _cfObject: CFSet { return unsafeBitCast(self, to: CFSet.self) }
    internal var _swiftObject: Set<NSObject> { return Set._unconditionallyBridgeFromObjectiveC(self) }
}

extension CFSet : _NSBridgeable, _SwiftBridgeable {
    internal var _nsObject: NSSet { return unsafeBitCast(self, to: NSSet.self) }
    internal var _swiftObject: Set<NSObject> { return _nsObject._swiftObject }
}

extension NSMutableSet {
    internal var _cfMutableObject: CFMutableSet { return unsafeBitCast(self, to: CFMutableSet.self) }
}

extension Set : _NSBridgeable, _CFBridgeable {
    internal var _nsObject: NSSet { return _bridgeToObjectiveC() }
    internal var _cfObject: CFSet { return _nsObject._cfObject }
}

extension NSSet : Sequence {
    public typealias Iterator = NSEnumerator.Iterator
    public func makeIterator() -> Iterator {
        return self.objectEnumerator().makeIterator()
    }
}

extension NSSet : CustomReflectable {
    public var customMirror: Mirror { NSUnimplemented() }
}

open class NSMutableSet : NSSet {
    
    open func add(_ object: Any) {
        guard type(of: self) === NSMutableSet.self else {
            NSRequiresConcreteImplementation()
        }
        _storage.insert(_SwiftValue.store(object))
    }
    
    open func remove(_ object: Any) {
        guard type(of: self) === NSMutableSet.self else {
            NSRequiresConcreteImplementation()
        }

        _storage.remove(_SwiftValue.store(object))
    }
    
    override public init(objects: UnsafePointer<AnyObject>!, count cnt: Int) {
        super.init(objects: objects, count: cnt)
    }

    public convenience init() {
        self.init(capacity: 0)
    }
    
    public required init(capacity numItems: Int) {
        super.init(objects: [], count: 0)
    }
    
    public required convenience init?(coder aDecoder: NSCoder) {
        NSUnimplemented()
    }
    
    open func addObjects(from array: [Any]) {
        if type(of: self) === NSMutableSet.self {
            for case let obj in array {
                _storage.insert(_SwiftValue.store(obj))
            }
        } else {
            array.forEach(add)
        }
    }
    
    open func intersect(_ otherSet: Set<AnyHashable>) {
        if type(of: self) === NSMutableSet.self {
            _storage.formIntersection(otherSet.map { _SwiftValue.store($0) })
        } else {
            for obj in self {
                if !otherSet.contains(obj as! AnyHashable) {
                    remove(obj)
                }
            }
        }
    }
    
    open func minus(_ otherSet: Set<AnyHashable>) {
        if type(of: self) === NSMutableSet.self {
            _storage.subtract(otherSet.map { _SwiftValue.store($0) })
        } else {
            otherSet.forEach(remove)
        }
    }
    
    open func removeAllObjects() {
        if type(of: self) === NSMutableSet.self {
            _storage.removeAll()
        } else {
            forEach(remove)
        }
    }
    
    open func union(_ otherSet: Set<AnyHashable>) {
        if type(of: self) === NSMutableSet.self {
            _storage.formUnion(otherSet.map { _SwiftValue.store($0) })
        } else {
            otherSet.forEach(add)
        }
    }
    
    open func setSet(_ otherSet: Set<AnyHashable>) {
        if type(of: self) === NSMutableSet.self {
            _storage = Set(otherSet.map { _SwiftValue.store($0) })
        } else {
            removeAllObjects()
            union(otherSet)
        }
    }

}

/****************	Counted Set	****************/
open class NSCountedSet : NSMutableSet {
    internal var _table: Dictionary<NSObject, Int>

    public required init(capacity numItems: Int) {
        _table = Dictionary<NSObject, Int>()
        super.init(capacity: numItems)
    }

    public  convenience init() {
        self.init(capacity: 0)
    }

    public convenience init(array: [Any]) {
        self.init(capacity: array.count)
        for object in array {
            let value = _SwiftValue.store(object)
            if let count = _table[value] {
                _table[value] = count + 1
            } else {
                _table[value] = 1
                _storage.insert(value)
            }
        }
    }

    public convenience init(set: Set<AnyHashable>) {
        self.init(array: set.map { $0 })
    }

    public required convenience init?(coder: NSCoder) { NSUnimplemented() }

    open override func copy(with zone: NSZone? = nil) -> Any {
        if type(of: self) === NSCountedSet.self {
            let countedSet = NSCountedSet()
            countedSet._storage = self._storage
            countedSet._table = self._table
            return countedSet
        }
        return NSCountedSet(array: self.allObjects)
    }

    open override func mutableCopy(with zone: NSZone? = nil) -> Any {
        if type(of: self) === NSCountedSet.self {
            let countedSet = NSCountedSet()
            countedSet._storage = self._storage
            countedSet._table = self._table
            return countedSet
        }
        return NSCountedSet(array: self.allObjects)
    }

    open func count(for object: Any) -> Int {
        guard type(of: self) === NSCountedSet.self else {
            NSRequiresConcreteImplementation()
        }
        let value = _SwiftValue.store(object)
        guard let count = _table[value] else {
            return 0
        }
        return count
    }

    open override func add(_ object: Any) {
        guard type(of: self) === NSCountedSet.self else {
            NSRequiresConcreteImplementation()
        }
        let value = _SwiftValue.store(object)
        if let count = _table[value] {
            _table[value] = count + 1
        } else {
            _table[value] = 1
            _storage.insert(value)
        }
    }

    open override func remove(_ object: Any) {
        guard type(of: self) === NSCountedSet.self else {
            NSRequiresConcreteImplementation()
        }
        let value = _SwiftValue.store(object)
        guard let count = _table[value] else {
            return
        }

        if count > 1 {
            _table[value] = count - 1
        } else {
            _table[value] = nil
            _storage.remove(value)
        }
    }

    open override func removeAllObjects() {
        if type(of: self) === NSCountedSet.self {
            _storage.removeAll()
            _table.removeAll()
        } else {
            forEach(remove)
        }
    }
}

extension NSSet : _StructTypeBridgeable {
    public typealias _StructType = Set<AnyHashable>
    
    public func _bridgeToSwift() -> _StructType {
        return _StructType._unconditionallyBridgeFromObjectiveC(self)
    }
}
