// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 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

public let NSGlobalDomain: String = "NSGlobalDomain"
public let NSArgumentDomain: String = "NSArgumentDomain"
public let NSRegistrationDomain: String = "NSRegistrationDomain"

private var registeredDefaults = [String: AnyObject]()
private var sharedDefaults = NSUserDefaults()

public class NSUserDefaults : NSObject {
    private let suite: String?
    
    public class func standardUserDefaults() -> NSUserDefaults {
        return sharedDefaults
    }
    
    public class func resetStandardUserDefaults() {
        //sharedDefaults.synchronize()
        //sharedDefaults = NSUserDefaults()
    }
    
    public convenience override init() {
        self.init(suiteName: nil)!
    }
    
    /// nil suite means use the default search list that +standardUserDefaults uses
    public init?(suiteName suitename: String?) {
        suite = suitename
    }
    
    public func objectForKey(defaultName: String) -> AnyObject? {
        func getFromRegistered() -> AnyObject? {
            return registeredDefaults[defaultName]
        }
        
        guard let anObj = CFPreferencesCopyAppValue(defaultName._cfObject, suite?._cfObject ?? kCFPreferencesCurrentApplication) else {
            return getFromRegistered()
        }
        
        //Force the returned value to an NSObject
        switch CFGetTypeID(anObj) {
        case CFStringGetTypeID():
            return (anObj as! CFString)._nsObject
            
        case CFNumberGetTypeID():
            return (anObj as! CFNumber)._nsObject
            
        case CFURLGetTypeID():
            return (anObj as! CFURL)._nsObject
            
        case CFArrayGetTypeID():
            return (anObj as! CFArray)._nsObject
            
        case CFDictionaryGetTypeID():
            return (anObj as! CFDictionary)._nsObject

        case CFDataGetTypeID():
            return (anObj as! CFData)._nsObject
            
        default:
            return getFromRegistered()
        }
    }
    public func setObject(value: AnyObject?, forKey defaultName: String) {
        guard let value = value else {
            CFPreferencesSetAppValue(defaultName._cfObject, nil, suite?._cfObject ?? kCFPreferencesCurrentApplication)
            return
        }
        
        var cfType: CFTypeRef? = nil
		
		//FIXME: is this needed? Am I overcomplicating things?
        //Foundation types
        if let bType = value as? NSNumber {
            cfType = bType._cfObject
        } else if let bType = value as? NSString {
            cfType = bType._cfObject
        } else if let bType = value as? NSArray {
            cfType = bType._cfObject
        } else if let bType = value as? NSDictionary {
            cfType = bType._cfObject
        } else if let bType = value as? NSURL {
			setURL(bType, forKey: defaultName)
			return
        } else if let bType = value as? NSData {
            cfType = bType._cfObject
        }
        
        CFPreferencesSetAppValue(defaultName._cfObject, cfType, suite?._cfObject ?? kCFPreferencesCurrentApplication)
    }
    public func removeObjectForKey(defaultName: String) {
        CFPreferencesSetAppValue(defaultName._cfObject, nil, suite?._cfObject ?? kCFPreferencesCurrentApplication)
    }
    
    public func stringForKey(defaultName: String) -> String? {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSString else {
            return nil
        }
        return bVal._swiftObject
    }
    public func arrayForKey(defaultName: String) -> [AnyObject]? {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSArray else {
            return nil
        }
        return bVal._swiftObject
    }
    public func dictionaryForKey(defaultName: String) -> [String : AnyObject]? {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSDictionary else {
            return nil
        }
        //This got out of hand fast...
        let cVal = bVal._swiftObject
        enum convErr: ErrorProtocol {
            case ConvErr
        }
        do {
            let dVal = try cVal.map({ (key, val) -> (String, AnyObject) in
                if let strKey = key as? NSString {
                    return (strKey._swiftObject, val)
                } else {
                    throw convErr.ConvErr
                }
            })
            var eVal = [String : AnyObject]()
            
            for (key, value) in dVal {
                eVal[key] = value
            }
            
            return eVal
        } catch _ { }
        return nil
    }
    public func dataForKey(defaultName: String) -> NSData? {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSData else {
            return nil
        }
        return bVal
    }
    public func stringArrayForKey(defaultName: String) -> [String]? {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSArray else {
            return nil
        }
        return _expensivePropertyListConversion(bVal) as? [String]
    }
    public func integerForKey(defaultName: String) -> Int {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
            return 0
        }
        return bVal.integerValue
    }
    public func floatForKey(defaultName: String) -> Float {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
            return 0
        }
        return bVal.floatValue
    }
    public func doubleForKey(defaultName: String) -> Double {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
            return 0
        }
        return bVal.doubleValue
    }
    public func boolForKey(defaultName: String) -> Bool {
        guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
            return false
        }
        return bVal.boolValue
    }
    public func URLForKey(defaultName: String) -> NSURL? {
        guard let aVal = objectForKey(defaultName) else {
            return nil
        }
        
        if let bVal = aVal as? NSString {
            let cVal = bVal.stringByExpandingTildeInPath
            
            return NSURL(fileURLWithPath: cVal)
        } else if let bVal = aVal as? NSData {
            return NSKeyedUnarchiver.unarchiveObjectWithData(bVal) as? NSURL
        }
        
        return nil
    }
    
    public func setInteger(value: Int, forKey defaultName: String) {
        setObject(NSNumber(integer: value), forKey: defaultName)
    }
    public func setFloat(value: Float, forKey defaultName: String) {
        setObject(NSNumber(float: value), forKey: defaultName)
    }
    public func setDouble(value: Double, forKey defaultName: String) {
        setObject(NSNumber(double: value), forKey: defaultName)
    }
    public func setBool(value: Bool, forKey defaultName: String) {
        setObject(NSNumber(bool: value), forKey: defaultName)
    }
    public func setURL(url: NSURL?, forKey defaultName: String) {
		if let url = url {
            //FIXME: CFURLIsFileReferenceURL is limited to OS X/iOS
            #if os(OSX) || os(iOS)
                //FIXME: no SwiftFoundation version of CFURLIsFileReferenceURL at time of writing!
                if !CFURLIsFileReferenceURL(url._cfObject) {
                    //FIXME: stringByAbbreviatingWithTildeInPath isn't implemented in SwiftFoundation
                    //TODO: use stringByAbbreviatingWithTildeInPath when it is
                    let urlPath = url.path!
                    
                    setObject(urlPath._nsObject, forKey: defaultName)
                    return
                }
            #else
                if let urlPath = url.path {
                    //FIXME: stringByAbbreviatingWithTildeInPath isn't implemented in SwiftFoundation
                    //TODO: use stringByAbbreviatingWithTildeInPath when it is
                    setObject(urlPath._nsObject, forKey: defaultName)
                    return
                }
            #endif
            let data = NSKeyedArchiver.archivedDataWithRootObject(url)
            setObject(data, forKey: defaultName)
        } else {
            setObject(nil, forKey: defaultName)
        }
    }
    
    public func registerDefaults(registrationDictionary: [String : AnyObject]) {
        for (key, value) in registrationDictionary {
            registeredDefaults[key] = value
        }
    }
    
    public func addSuiteNamed(suiteName: String) {
        CFPreferencesAddSuitePreferencesToApp(kCFPreferencesCurrentApplication, suiteName._cfObject)
    }
    public func removeSuiteNamed(suiteName: String) {
        CFPreferencesRemoveSuitePreferencesFromApp(kCFPreferencesCurrentApplication, suiteName._cfObject)
    }
    
    public func dictionaryRepresentation() -> [String : AnyObject] {
        NSUnimplemented()
        /*
        Currently crashes the compiler.
        guard let aPref = CFPreferencesCopyMultiple(nil, kCFPreferencesCurrentApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost),
            bPref = (aPref._swiftObject) as? [NSString: AnyObject] else {
                return registeredDefaults
        }
        var allDefaults = registeredDefaults
        
        for (key, value) in bPref {
            allDefaults[key._swiftObject] = value
        }
        
        return allDefaults
        */
    }
    
    public var volatileDomainNames: [String] { NSUnimplemented() }
    public func volatileDomainForName(domainName: String) -> [String : AnyObject] { NSUnimplemented() }
    public func setVolatileDomain(domain: [String : AnyObject], forName domainName: String) { NSUnimplemented() }
    public func removeVolatileDomainForName(domainName: String) { NSUnimplemented() }
    
    public func persistentDomainForName(domainName: String) -> [String : AnyObject]? { NSUnimplemented() }
    public func setPersistentDomain(domain: [String : AnyObject], forName domainName: String) { NSUnimplemented() }
    public func removePersistentDomainForName(domainName: String) { NSUnimplemented() }
    
    public func synchronize() -> Bool {
        return CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)
    }
    
    public func objectIsForcedForKey(key: String) -> Bool { NSUnimplemented() }
    public func objectIsForcedForKey(key: String, inDomain domain: String) -> Bool { NSUnimplemented() }
}

public let NSUserDefaultsDidChangeNotification: String = "NSUserDefaultsDidChangeNotification"

