import Foundation

public class SynchronizedMap<K: Hashable, V>: NSObject {

    // MARK: Public

    public func add(key: K, value: V) {
        lock.lock()
        defer {
            lock.unlock()
        }
        map[key] = value
    }

    public func get(key: K) -> V? {
        lock.lock()
        defer {
            lock.unlock()
        }
        return map[key]
    }

    @discardableResult
    public func remove(key: K) -> V? {
        lock.lock()
        defer {
            lock.unlock()
        }
        return map.removeValue(forKey: key)
    }

    @discardableResult
    public func removeAll() -> any Collection<V> {
        lock.lock()
        defer {
            lock.unlock()
        }
        let copy = map.values
        map = [:]
        return copy
    }

    @discardableResult
    public func keySet() -> any Collection<K> {
        lock.lock()
        defer {
            lock.unlock()
        }
        return map.keys
    }

    // MARK: Private

    private let lock = NSLock()
    private var map: [K: V] = [:]

}
