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

internal func __NSLocaleIsAutoupdating(_ locale: NSLocale) -> Bool {
    return false // Auto-updating is only on Darwin
}

internal func __NSLocaleCurrent() -> NSLocale {
    return CFLocaleCopyCurrent()._nsObject
}

/**
 `Locale` encapsulates information about linguistic, cultural, and technological conventions and standards. Examples of information encapsulated by a locale include the symbol used for the decimal separator in numbers and the way dates are formatted.
 
 Locales are typically used to provide, format, and interpret information about and according to the user’s customs and preferences. They are frequently used in conjunction with formatters. Although you can use many locales, you usually use the one associated with the current user.
 */
public struct Locale : CustomStringConvertible, CustomDebugStringConvertible, Hashable, Equatable, ReferenceConvertible {
    public typealias ReferenceType = NSLocale
    
    public typealias LanguageDirection = NSLocale.LanguageDirection
    
    internal var _wrapped : NSLocale
    internal var _autoupdating : Bool
    
    /// Returns the user's current locale.
    public static var current : Locale {
        return Locale(adoptingReference: __NSLocaleCurrent(), autoupdating: false)
    }
    
    /// Returns a locale which tracks the user's current preferences.
    ///
    /// If mutated, this Locale will no longer track the user's preferences.
    ///
    /// - note: The autoupdating Locale will only compare equal to another autoupdating Locale.
    public static var autoupdatingCurrent : Locale {
        // swift-corelibs-foundation does not yet support autoupdating, but we can return the current locale (which will not change).
        return Locale(adoptingReference: __NSLocaleCurrent(), autoupdating: true)
    }
    
    @available(*, unavailable, message: "Consider using the user's locale or nil instead, depending on use case")
    public static var system : Locale { fatalError() }
    
    // MARK: -
    //
    
    /// Return a locale with the specified identifier.
    public init(identifier: String) {
        _wrapped = NSLocale(localeIdentifier: identifier)
        _autoupdating = false
    }
    
    internal init(reference: NSLocale) {
        _wrapped = reference.copy() as! NSLocale
        if __NSLocaleIsAutoupdating(reference) {
            _autoupdating = true
        } else {
            _autoupdating = false
        }
    }
    
    private init(adoptingReference reference: NSLocale, autoupdating: Bool) {
        _wrapped = reference
        _autoupdating = autoupdating
    }
    
    // MARK: -
    //
    
    /// Returns a localized string for a specified identifier.
    ///
    /// For example, in the "en" locale, the result for `"es"` is `"Spanish"`.
    public func localizedString(forIdentifier identifier: String) -> String? {
        return _wrapped.displayName(forKey: .identifier, value: identifier)
    }
    
    /// Returns a localized string for a specified language code.
    ///
    /// For example, in the "en" locale, the result for `"es"` is `"Spanish"`.
    public func localizedString(forLanguageCode languageCode: String) -> String? {
        return _wrapped.displayName(forKey: .languageCode, value: languageCode)
    }
    
    /// Returns a localized string for a specified region code.
    ///
    /// For example, in the "en" locale, the result for `"fr"` is `"France"`.
    public func localizedString(forRegionCode regionCode: String) -> String? {
        return _wrapped.displayName(forKey: .countryCode, value: regionCode)
    }
    
    /// Returns a localized string for a specified script code.
    ///
    /// For example, in the "en" locale, the result for `"Hans"` is `"Simplified Han"`.
    public func localizedString(forScriptCode scriptCode: String) -> String? {
        return _wrapped.displayName(forKey: .scriptCode, value: scriptCode)
    }
    
    /// Returns a localized string for a specified variant code.
    ///
    /// For example, in the "en" locale, the result for `"POSIX"` is `"Computer"`.
    public func localizedString(forVariantCode variantCode: String) -> String? {
        return _wrapped.displayName(forKey: .variantCode, value: variantCode)
    }
    
    /// Returns a localized string for a specified `Calendar.Identifier`.
    ///
    /// For example, in the "en" locale, the result for `.buddhist` is `"Buddhist Calendar"`.
    public func localizedString(for calendarIdentifier: Calendar.Identifier) -> String? {
        // NSLocale doesn't export a constant for this
        let result = CFLocaleCopyDisplayNameForPropertyValue(unsafeBitCast(_wrapped, to: CFLocale.self), kCFLocaleCalendarIdentifier, Calendar._toNSCalendarIdentifier(calendarIdentifier).rawValue._cfObject)._swiftObject
        return result
    }
    
    /// Returns a localized string for a specified ISO 4217 currency code.
    ///
    /// For example, in the "en" locale, the result for `"USD"` is `"US Dollar"`.
    /// - seealso: `Locale.isoCurrencyCodes`
    public func localizedString(forCurrencyCode currencyCode: String) -> String? {
        return _wrapped.displayName(forKey: .currencyCode, value: currencyCode)
    }
    
    /// Returns a localized string for a specified ICU collation identifier.
    ///
    /// For example, in the "en" locale, the result for `"phonebook"` is `"Phonebook Sort Order"`.
    public func localizedString(forCollationIdentifier collationIdentifier: String) -> String? {
        return _wrapped.displayName(forKey: .collationIdentifier, value: collationIdentifier)
    }
    
    /// Returns a localized string for a specified ICU collator identifier.
    public func localizedString(forCollatorIdentifier collatorIdentifier: String) -> String? {
        return _wrapped.displayName(forKey: .collatorIdentifier, value: collatorIdentifier)
    }
    
    // MARK: -
    //
    
    /// Returns the identifier of the locale.
    public var identifier: String {
        return _wrapped.localeIdentifier
    }
    
    /// Returns the language code of the locale, or nil if has none.
    ///
    /// For example, for the locale "zh-Hant-HK", returns "zh".
    public var languageCode: String? {
        return _wrapped.object(forKey: .languageCode) as? String
    }
    
    /// Returns the region code of the locale, or nil if it has none.
    ///
    /// For example, for the locale "zh-Hant-HK", returns "HK".
    public var regionCode: String? {
        // n.b. this is called countryCode in ObjC
        if let result = _wrapped.object(forKey: .countryCode) as? String {
            if result.isEmpty {
                return nil
            } else {
                return result
            }
        } else {
            return nil
        }
    }
    
    /// Returns the script code of the locale, or nil if has none.
    ///
    /// For example, for the locale "zh-Hant-HK", returns "Hant".
    public var scriptCode: String? {
        return _wrapped.object(forKey: .scriptCode) as? String
    }
    
    /// Returns the variant code for the locale, or nil if it has none.
    ///
    /// For example, for the locale "en_POSIX", returns "POSIX".
    public var variantCode: String? {
        if let result = _wrapped.object(forKey: .variantCode) as? String {
            if result.isEmpty {
                return nil
            } else {
                return result
            }
        } else {
            return nil
        }
    }
    
    /// Returns the exemplar character set for the locale, or nil if has none.
    public var exemplarCharacterSet: CharacterSet? {
        return _wrapped.object(forKey: .exemplarCharacterSet) as? CharacterSet
    }
    
    /// Returns the calendar for the locale, or the Gregorian calendar as a fallback.
    public var calendar: Calendar {
        // NSLocale should not return nil here
        if let result = _wrapped.object(forKey: .calendar) as? Calendar {
            return result
        } else {
            return Calendar(identifier: .gregorian)
        }
    }
    
    /// Returns the collation identifier for the locale, or nil if it has none.
    ///
    /// For example, for the locale "en_US@collation=phonebook", returns "phonebook".
    public var collationIdentifier: String? {
        return _wrapped.object(forKey: .collationIdentifier) as? String
    }
    
    /// Returns true if the locale uses the metric system.
    ///
    /// -seealso: MeasurementFormatter
    public var usesMetricSystem: Bool {
        // NSLocale should not return nil here, but just in case
        if let result = _wrapped.object(forKey: .usesMetricSystem) as? Bool {
            return result
        } else {
            return false
        }
    }
    
    /// Returns the decimal separator of the locale.
    ///
    /// For example, for "en_US", returns ".".
    public var decimalSeparator: String? {
        return _wrapped.object(forKey: .decimalSeparator) as? String
    }
    
    /// Returns the grouping separator of the locale.
    ///
    /// For example, for "en_US", returns ",".
    public var groupingSeparator: String? {
        return _wrapped.object(forKey: .groupingSeparator) as? String
    }
    
    /// Returns the currency symbol of the locale.
    ///
    /// For example, for "zh-Hant-HK", returns "HK$".
    public var currencySymbol: String? {
        return _wrapped.object(forKey: .currencySymbol) as? String
    }
    
    /// Returns the currency code of the locale.
    ///
    /// For example, for "zh-Hant-HK", returns "HKD".
    public var currencyCode: String? {
        return _wrapped.object(forKey: .currencyCode) as? String
    }
    
    /// Returns the collator identifier of the locale.
    public var collatorIdentifier: String? {
        return _wrapped.object(forKey: .collatorIdentifier) as? String
    }
    
    /// Returns the quotation begin delimiter of the locale.
    ///
    /// For example, returns `“` for "en_US", and `「` for "zh-Hant-HK".
    public var quotationBeginDelimiter: String? {
        return _wrapped.object(forKey: .quotationBeginDelimiterKey) as? String
    }
    
    /// Returns the quotation end delimiter of the locale.
    ///
    /// For example, returns `”` for "en_US", and `」` for "zh-Hant-HK".
    public var quotationEndDelimiter: String? {
        return _wrapped.object(forKey: .quotationEndDelimiterKey) as? String
    }
    
    /// Returns the alternate quotation begin delimiter of the locale.
    ///
    /// For example, returns `‘` for "en_US", and `『` for "zh-Hant-HK".
    public var alternateQuotationBeginDelimiter: String? {
        return _wrapped.object(forKey: .alternateQuotationBeginDelimiterKey) as? String
    }
    
    /// Returns the alternate quotation end delimiter of the locale.
    ///
    /// For example, returns `’` for "en_US", and `』` for "zh-Hant-HK".
    public var alternateQuotationEndDelimiter: String? {
        return _wrapped.object(forKey: .alternateQuotationEndDelimiterKey) as? String
    }
    
    // MARK: -
    //
    
    /// Returns a list of available `Locale` identifiers.
    public static var availableIdentifiers: [String] {
        return NSLocale.availableLocaleIdentifiers
    }
    
    /// Returns a list of available `Locale` language codes.
    public static var isoLanguageCodes: [String] {
        return NSLocale.isoLanguageCodes
    }
    
    /// Returns a list of available `Locale` region codes.
    public static var isoRegionCodes: [String] {
        // This was renamed from Obj-C
        return NSLocale.isoCountryCodes
    }
    
    /// Returns a list of available `Locale` currency codes.
    public static var isoCurrencyCodes: [String] {
        return NSLocale.isoCurrencyCodes
    }
    
    /// Returns a list of common `Locale` currency codes.
    public static var commonISOCurrencyCodes: [String] {
        return NSLocale.commonISOCurrencyCodes
    }
    
    /// Returns a list of the user's preferred languages.
    ///
    /// - note: `Bundle` is responsible for determining the language that your application will run in, based on the result of this API and combined with the languages your application supports.
    /// - seealso: `Bundle.preferredLocalizations(from:)`
    /// - seealso: `Bundle.preferredLocalizations(from:forPreferences:)`
    public static var preferredLanguages: [String] {
        return NSLocale.preferredLanguages
    }
    
    /// Returns a dictionary that splits an identifier into its component pieces.
    public static func components(fromIdentifier string: String) -> [String : String] {
        return NSLocale.components(fromLocaleIdentifier: string)
    }
    
    /// Constructs an identifier from a dictionary of components.
    public static func identifier(fromComponents components: [String : String]) -> String {
        return NSLocale.localeIdentifier(fromComponents: components)
    }
    
    /// Returns a canonical identifier from the given string.
    public static func canonicalIdentifier(from string: String) -> String {
        return NSLocale.canonicalLocaleIdentifier(from: string)
    }
    
    /// Returns a canonical language identifier from the given string.
    public static func canonicalLanguageIdentifier(from string: String) -> String {
        return NSLocale.canonicalLanguageIdentifier(from: string)
    }
    
    /// Returns the `Locale` identifier from a given Windows locale code, or nil if it could not be converted.
    public static func identifier(fromWindowsLocaleCode code: Int) -> String? {
        return NSLocale.localeIdentifier(fromWindowsLocaleCode: UInt32(code))
    }
    
    /// Returns the Windows locale code from a given identifier, or nil if it could not be converted.
    public static func windowsLocaleCode(fromIdentifier identifier: String) -> Int? {
        let result = NSLocale.windowsLocaleCode(fromLocaleIdentifier: identifier)
        if result == 0 {
            return nil
        } else {
            return Int(result)
        }
    }
    
    /// Returns the character direction for a specified language code.
    public static func characterDirection(forLanguage isoLangCode: String) -> Locale.LanguageDirection {
        return NSLocale.characterDirection(forLanguage: isoLangCode)
    }
    
    /// Returns the line direction for a specified language code.
    public static func lineDirection(forLanguage isoLangCode: String) -> Locale.LanguageDirection {
        return NSLocale.lineDirection(forLanguage: isoLangCode)
    }
    
    // MARK: -
    
    @available(*, unavailable, renamed: "init(identifier:)")
    public init(localeIdentifier: String) { fatalError() }
    
    @available(*, unavailable, renamed: "identifier")
    public var localeIdentifier: String { fatalError() }
    
    @available(*, unavailable, renamed: "localizedString(forIdentifier:)")
    public func localizedString(forLocaleIdentifier localeIdentifier: String) -> String { fatalError() }
    
    @available(*, unavailable, renamed: "availableIdentifiers")
    public static var availableLocaleIdentifiers: [String] { fatalError() }
    
    @available(*, unavailable, renamed: "components(fromIdentifier:)")
    public static func components(fromLocaleIdentifier string: String) -> [String : String] { fatalError() }
    
    @available(*, unavailable, renamed: "identifier(fromComponents:)")
    public static func localeIdentifier(fromComponents dict: [String : String]) -> String { fatalError() }
    
    @available(*, unavailable, renamed: "canonicalIdentifier(from:)")
    public static func canonicalLocaleIdentifier(from string: String) -> String { fatalError() }
    
    @available(*, unavailable, renamed: "identifier(fromWindowsLocaleCode:)")
    public static func localeIdentifier(fromWindowsLocaleCode lcid: UInt32) -> String? { fatalError() }
    
    @available(*, unavailable, renamed: "windowsLocaleCode(fromIdentifier:)")
    public static func windowsLocaleCode(fromLocaleIdentifier localeIdentifier: String) -> UInt32 { fatalError() }
    
    @available(*, unavailable, message: "use regionCode instead")
    public var countryCode: String { fatalError() }
    
    @available(*, unavailable, message: "use localizedString(forRegionCode:) instead")
    public func localizedString(forCountryCode countryCode: String) -> String { fatalError() }
    
    @available(*, unavailable, renamed: "isoRegionCodes")
    public static var isoCountryCodes: [String] { fatalError() }
    
    // MARK: -
    //
    
    public var description: String {
        return _wrapped.description
    }
    
    public var debugDescription : String {
        return _wrapped.debugDescription
    }
    
    public var hashValue : Int {
        if _autoupdating {
            return 1
        } else {
            return _wrapped.hash
        }
    }

    public static func ==(lhs: Locale, rhs: Locale) -> Bool {
        if lhs._autoupdating || rhs._autoupdating {
            return lhs._autoupdating == rhs._autoupdating
        } else {
            return lhs._wrapped.isEqual(rhs._wrapped)
        }
    }
}


extension Locale : _ObjectTypeBridgeable {
    public static func _isBridgedToObjectiveC() -> Bool {
        return true
    }
    
    @_semantics("convertToObjectiveC")
    public func _bridgeToObjectiveC() -> NSLocale {
        return _wrapped
    }
    
    public static func _forceBridgeFromObjectiveC(_ input: NSLocale, result: inout Locale?) {
        if !_conditionallyBridgeFromObjectiveC(input, result: &result) {
            fatalError("Unable to bridge \(NSLocale.self) to \(self)")
        }
    }
    
    public static func _conditionallyBridgeFromObjectiveC(_ input: NSLocale, result: inout Locale?) -> Bool {
        result = Locale(reference: input)
        return true
    }
    
    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSLocale?) -> Locale {
        var result: Locale? = nil
        _forceBridgeFromObjectiveC(source!, result: &result)
        return result!
    }
}

extension Locale : Codable {
    private enum CodingKeys : Int, CodingKey {
        case identifier
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let identifier = try container.decode(String.self, forKey: .identifier)
        self.init(identifier: identifier)
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.identifier, forKey: .identifier)
    }
}
