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


public class NSCache : NSObject {
    private class NSCacheEntry {
        var key: AnyObject
        var value: AnyObject
        var cost: Int
        var prevByCost: NSCacheEntry?
        var nextByCost: NSCacheEntry?
        init(key: AnyObject, value: AnyObject, cost: Int) {
            self.key = key
            self.value = value
            self.cost = cost
        }
    }
    
    private var _entries = Dictionary<UnsafePointer<Void>, NSCacheEntry>()
    private let _lock = NSLock()
    private var _totalCost = 0
    private var _byCost: NSCacheEntry?
    
    public var name: String = ""
    public var totalCostLimit: Int = -1 // limits are imprecise/not strict
    public var countLimit: Int = -1 // limits are imprecise/not strict
    public var evictsObjectsWithDiscardedContent: Bool = false

    public override init() {
        
    }
    
    public weak var delegate: NSCacheDelegate?
    
    public func object(forKey key: AnyObject) -> AnyObject? {
        var object: AnyObject?
        
        let keyRef = unsafeBitCast(key, to: UnsafePointer<Void>.self)
        
        _lock.lock()
        if let entry = _entries[keyRef] {
            object = entry.value
        }
        _lock.unlock()
        
        return object
    }
    
    public func setObject(_ obj: AnyObject, forKey key: AnyObject) {
        setObject(obj, forKey: key, cost: 0)
    }
    
    private func remove(_ entry: NSCacheEntry) {
        let oldPrev = entry.prevByCost
        let oldNext = entry.nextByCost
        oldPrev?.nextByCost = oldNext
        oldNext?.prevByCost = oldPrev
        if entry === _byCost {
            _byCost = entry.nextByCost
        }
    }
   
    private func insert(_ entry: NSCacheEntry) {
        if _byCost == nil {
            _byCost = entry
        } else {
            var element = _byCost
            while let e = element {
                if e.cost > entry.cost {
                    let newPrev = e.prevByCost
                    entry.prevByCost = newPrev
                    entry.nextByCost = e
                    break
                }
                element = e.nextByCost
            }
        }
    }
    
    public func setObject(_ obj: AnyObject, forKey key: AnyObject, cost g: Int) {
        let keyRef = unsafeBitCast(key, to: UnsafePointer<Void>.self)
        
        _lock.lock()
        _totalCost += g
        
        var purgeAmount = 0
        if totalCostLimit > 0 {
            purgeAmount = (_totalCost + g) - totalCostLimit
        }
        
        var purgeCount = 0
        if countLimit > 0 {
            purgeCount = (_entries.count + 1) - countLimit
        }
        
        if let entry = _entries[keyRef] {
            entry.value = obj
            if entry.cost != g {
                entry.cost = g
                remove(entry)
                insert(entry)
            }
        } else {
            _entries[keyRef] = NSCacheEntry(key: key, value: obj, cost: g)
        }
        _lock.unlock()
        
        var toRemove = [NSCacheEntry]()
        
        if purgeAmount > 0 {
            _lock.lock()
            while _totalCost - totalCostLimit > 0 {
                if let entry = _byCost {
                    _totalCost -= entry.cost
                    toRemove.append(entry)
                    remove(entry)
                } else {
                    break
                }
            }
            if countLimit > 0 {
                purgeCount = (_entries.count - toRemove.count) - countLimit
            }
            _lock.unlock()
        }
        
        if purgeCount > 0 {
            _lock.lock()
            while (_entries.count - toRemove.count) - countLimit > 0 {
                if let entry = _byCost {
                    _totalCost -= entry.cost
                    toRemove.append(entry)
                    remove(entry)
                } else {
                    break
                }
            }
            _lock.unlock()
        }
        
        if let del = delegate {
            for entry in toRemove {
                del.cache(self, willEvictObject: entry.value)
            }
        }
        
        _lock.lock()
        for entry in toRemove {
            _entries.removeValue(forKey: unsafeBitCast(entry.key, to: UnsafePointer<Void>.self)) // the cost list is already fixed up in the purge routines
        }
        _lock.unlock()
    }
    
    public func removeObject(forKey key: AnyObject) {
        let keyRef = unsafeBitCast(key, to: UnsafePointer<Void>.self)
        
        _lock.lock()
        if let entry = _entries.removeValue(forKey: keyRef) {
            _totalCost -= entry.cost
            remove(entry)
        }
        _lock.unlock()
    }
    
    public func removeAllObjects() {
        _lock.lock()
        _entries.removeAll()
        _byCost = nil
        _totalCost = 0
        _lock.unlock()
    }    
}

public protocol NSCacheDelegate : class {
    func cache(_ cache: NSCache, willEvictObject obj: AnyObject)
}

extension NSCacheDelegate {
    func cache(_ cache: NSCache, willEvictObject obj: AnyObject) {
        // Default implementation does nothing
    }
}
