//
//  YHLocalizable.swift
//  galaxy
//
//  Created by edy on 2024/1/11.
//  Copyright © 2024 www.davidhuang.com. All rights reserved.
//

import Foundation

private let kDefaultLanguage = "en"
private let kBaseBundle = "Base"
private let kCurrentLanguageKey = "YHCurrentLanguageKey"

extension Notification.Name {
    static let languageChanged = Notification.Name("YHLanguageChanged")
}

open class YHLocalizable {
    
    static let shared = YHLocalizable()

    open func currentBundle() -> Bundle {
        let bundle: Bundle = Bundle.main
        if let path = bundle.path(forResource: self.currentLanguage(), ofType: "lproj"),
            let bundle = Bundle(path: path) {
            return bundle
        } else if let path = bundle.path(forResource: kBaseBundle, ofType: "lproj"),
            let bundle = Bundle(path: path) {
            return bundle
        }
        return Bundle.main
    }

    /**
     *  List available languages
     *  - Returns: Array of available languages.
     */
    open func availableLanguages(_ excludeBase: Bool = false) -> [String] {
        var availableLanguages = Bundle.main.localizations
        if let indexOfBase = availableLanguages.firstIndex(of: "Base"), excludeBase == true {
            availableLanguages.remove(at: indexOfBase)
        }
        return availableLanguages
    }

    /**
     *  Current language
     *  - Returns: The current language. String.
     */
    open func currentLanguage() -> String {
        if let currentLanguage = UserDefaults.standard.object(forKey: kCurrentLanguageKey) as? String {
            return currentLanguage
        }
        return defaultLanguage()
    }

    /**
     *  Change the current language
     *  - Parameter language: Desired language.
     */
    open func setCurrentLanguage(_ language: String) {
        let selectedLanguage = availableLanguages().contains(language) ? language : defaultLanguage()
        if selectedLanguage != currentLanguage() {
            UserDefaults.standard.set(selectedLanguage, forKey: kCurrentLanguageKey)
            UserDefaults.standard.synchronize()
            NotificationCenter.default.post(name: .languageChanged, object: nil)
        }
    }

    /**
     *  Default language
     *  - Returns: The app's default language. String.
     */
    open func defaultLanguage() -> String {
        var defaultLanguage: String = String()
        guard let preferredLanguage = Bundle.main.preferredLocalizations.first else {
            return kDefaultLanguage
        }
        let availableLanguages: [String] = self.availableLanguages()
        if availableLanguages.contains(preferredLanguage) {
            defaultLanguage = preferredLanguage
        } else {
            defaultLanguage = kDefaultLanguage
        }
        return defaultLanguage
    }

    /**
     Resets the current language to the default
     */
    open func resetCurrentLanguageToDefault() {
        setCurrentLanguage(self.defaultLanguage())
    }

    /**
     *  Get the current language's display name for a language.
     *  - Parameter language: Desired language.
     *  - Returns: The localized string.
     */
    open func displayNameForLanguage(_ language: String) -> String {
        let locale: NSLocale = NSLocale(localeIdentifier: currentLanguage())
        if let displayName = locale.displayName(forKey: NSLocale.Key.identifier, value: language) {
            return displayName
        }
        return String()
    }
}

public extension String {
    /**
     *  Utility method for getting localized value
     */
    var local: String {
        return YHLocalizable.shared.currentBundle().localizedString(forKey: self, value: nil, table: nil)
    }

    func yhlocalized(tableName: String?, bundle: Bundle?) -> String {
        guard bundle != nil else {
            return Bundle.main.localizedString(forKey: self, value: nil, table: tableName)
        }
        return bundle!.localizedString(forKey: self, value: nil, table: tableName)
    }
}
