import UIKit
import TigaseSwift

// FIXME: solve linter suppressed issues
// swiftlint: disable force_unwrapping
extension XmppService {
    open func refreshVCard(account: BareJID, for jid: BareJID?, onSuccess: ((VCard) -> Void)?, onError: ((ErrorCondition?) -> Void)?) {
        guard let client = getClient(forJid: account) else {
            onError?(ErrorCondition.service_unavailable)
            return
        }

        retrieveVCard(account: account, for: jid == nil ? nil : JID(jid!), completionHandler: { result in
            switch result {
            case .success(let vcard):
                DispatchQueue.global(qos: .default).async() {
                    self.dbVCardsCache.updateVCard(for: jid ?? account, on: account, vcard: vcard)
                    onSuccess?(vcard)
                }

            case .failure(let errorCondition):
                onError?(errorCondition)
            }
        })
    }

    open func retrieveVCard(account: BareJID, for jid: JID?, completionHandler: @escaping (Result<VCard, ErrorCondition>) -> Void) {
        guard let client = getClient(forJid: account) else {
            completionHandler(.failure(ErrorCondition.service_unavailable))
            return
        }
        if let vcard4Module: VCard4Module = client.modulesManager.getModule(VCard4Module.ID) {
            retrieveVCard(module: vcard4Module, for: jid, completionHandler: { result in
                switch result {
                case .success(let vcard):
                    completionHandler(.success(vcard))

                case .failure(let errorCondition):
                    if let vcardTempModule: VCardTempModule = client.modulesManager.getModule(VCardTempModule.ID) {
                        self.retrieveVCard(module: vcardTempModule, for: jid, completionHandler: completionHandler)
                    } else {
                        completionHandler(.failure(errorCondition))
                    }
                }
            })
        } else if let vcardTempModule: VCardTempModule = client.modulesManager.getModule(VCardTempModule.ID) {
            retrieveVCard(module: vcardTempModule, for: jid, completionHandler: completionHandler)
        } else {
            completionHandler(.failure(.undefined_condition))
        }
    }

    private func retrieveVCard(module: VCardModuleProtocol, for jid: JID?, completionHandler: @escaping (Result<VCard, ErrorCondition>) -> Void) {
        module.retrieveVCard(from: jid, completionHandler: completionHandler)
    }

    open func publishVCard(account: BareJID, vcard: VCard, completionHandler: @escaping (Result<Void, ErrorCondition>) -> Void) {
        guard let client = getClient(forJid: account) else {
            completionHandler(.failure(ErrorCondition.service_unavailable))
            return
        }

        if let vcard4Module: VCard4Module = client.modulesManager.getModule(VCard4Module.ID) {
            vcard4Module.publishVCard(vcard, completionHandler: { result in
                switch result {
                case .success:
                    completionHandler(.success(Void()))

                case .failure(let error):
                    if let vcardTempModule: VCardTempModule = client.modulesManager.getModule(VCardTempModule.ID) {
                        vcardTempModule.publishVCard(vcard, completionHandler: completionHandler)
                    } else {
                        completionHandler(.failure(error))
                    }
                }
            })
        } else if let vcardTempModule: VCardTempModule = client.modulesManager.getModule(VCardTempModule.ID) {
            vcardTempModule.publishVCard(vcard, completionHandler: completionHandler)
        } else {
            completionHandler(.failure(ErrorCondition.service_unavailable))
        }
    }
}
