//
//  TUICallKitExtension.swift
//  TUICallKit
//
//  Created by vincepzhang on 2023/8/14.
//

import Foundation
import TUICore
import TUICallEngine

class TUICallKitExtension: NSObject, TUIExtensionProtocol {
    
    static let instance = TUICallKitExtension()
    var joinGroupCallViewModel = JoinInGroupCallViewModel()
    
    func launchCall(type: TUICallMediaType, groupID: String, pushVC: UINavigationController, isClassic: Bool) {
        if !groupID.isEmpty {
            var requestParam: [String: Any] = [:]
            requestParam[TUICore_TUIContactObjectFactory_SelectGroupMemberVC_GroupID] = groupID
            requestParam[TUICore_TUIContactObjectFactory_SelectGroupMemberVC_Name] =
            TUIGlobalization.getLocalizedString(forKey: "Make-a-call", bundle: TUIKitLocalizableBundle)
            let viewControllerKey = isClassic ? TUICore_TUIContactObjectFactory_SelectGroupMemberVC_Classic :
            TUICore_TUIContactObjectFactory_SelectGroupMemberVC_Minimalist
            pushVC.push(viewControllerKey, param: requestParam) { [weak self] responseData in
                guard let self = self else { return }
                guard let modelList = responseData[TUICore_TUIContactObjectFactory_SelectGroupMemberVC_ResultUserList]
                        as? [AnyObject] else { return }
                let userIDs: [String] = modelList.compactMap { $0.userId }
                self.startCall(groupID: groupID, userIDs: userIDs, callingType: type)
            }
        }
    }
    
    func startCall(groupID: String, userIDs: [String], callingType: TUICallMediaType) {
        let selector = NSSelectorFromString("setOnlineUserOnly")
        if TUICallEngine.createInstance().responds(to: selector) {
            TUICallEngine.createInstance().perform(selector, with: 0)
        }
        
        if groupID.isEmpty {
            guard let userID = userIDs.first else { return }
            TUICallKit.createInstance().call(userId: userID, callMediaType: callingType)
        } else {
            TUICallKit.createInstance().groupCall(groupId: groupID, userIdList: userIDs, callMediaType: callingType)
        }
    }
    
    func doResponseInputViewExtension(param: [String: Any], type: TUICallMediaType, isClassic: Bool) {
        let userID = param[TUICore_TUIChatExtension_InputViewMoreItem_UserID] as? String ?? ""
        let groupId = param[TUICore_TUIChatExtension_InputViewMoreItem_GroupID] as? String ?? ""
        let pushVC = param[TUICore_TUIChatExtension_InputViewMoreItem_PushVC] as? UINavigationController
        
        if !userID.isEmpty {
            startCall(groupID: "", userIDs: [userID], callingType: type)
        } else if !groupId.isEmpty {
            guard let pushVC = pushVC else { return }
            launchCall(type: type, groupID: groupId, pushVC: pushVC, isClassic: isClassic)
        }
    }
    
    // MARK: TUIExtensionProtocol
    func onRaiseExtension(_ extensionID: String, parentView: UIView, param: [AnyHashable : Any]?) -> Bool {
        if extensionID.isEmpty {
            return false
        }
        
        guard let groupId = param?[TUICore_TUIChatExtension_ChatViewTopArea_ChatID] as? String,
              let isGroup = param?[TUICore_TUIChatExtension_ChatViewTopArea_IsGroup], isGroup as! String == "1" else {
            return false
        }
        
        if extensionID == TUICore_TUIChatExtension_ChatViewTopArea_ClassicExtensionID ||
            extensionID == TUICore_TUIChatExtension_ChatViewTopArea_MinimalistExtensionID {
            let joinGroupCallView = JoinInGroupCallView()
            joinGroupCallViewModel.setJoinGroupCallView(joinGroupCallView)
            joinGroupCallViewModel.getGroupAttributes(groupId)
            parentView.subviews.forEach {
                if $0 is JoinInGroupCallView {
                    $0.removeFromSuperview()
                }
            }
            parentView.addSubview(joinGroupCallView)
            return true
        }
        
        return false
    }
    
    func onGetExtension(_ extensionID: String, param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
        if extensionID.isEmpty {
            return nil
        }
        
        if extensionID == TUICore_TUIChatExtension_NavigationMoreItem_MinimalistExtensionID {
            return getNavigationMoreItemExtensionForMinimalistChat(param: param)
        } else if extensionID == TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID {
            return getInputViewMoreItemExtensionForClassicChat(param: param)
        } else if extensionID == TUICore_TUIContactExtension_FriendProfileActionMenu_ClassicExtensionID {
            return getFriendProfileActionMenuExtensionForClassicContact(param: param)
        } else if extensionID == TUICore_TUIContactExtension_FriendProfileActionMenu_MinimalistExtensionID {
            return getFriendProfileActionMenuExtensionForMinimalistContact(param: param)
        } else if extensionID == TUICore_TUIContactExtension_GroupInfoCardActionMenu_MinimalistExtensionID {
            return getGroupInfoCardActionMenuExtensionForMinimalistGroup(param: param)
        } else {
            return nil
        }
    }
    
    func getNavigationMoreItemExtensionForMinimalistChat(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
        guard let param = param else { return nil }
        
        let onClick: ([AnyHashable : Any]?, TUICallMediaType) -> Void = { [weak self] param, type in
            guard let self = self else { return }
            guard let param = param else { return }
            let userID = param[TUICore_TUIChatExtension_NavigationMoreItem_UserID] as? String ?? ""
            let groupID = param[TUICore_TUIChatExtension_NavigationMoreItem_GroupID] as? String ?? ""
            let pushVC = param[TUICore_TUIChatExtension_NavigationMoreItem_PushVC] as? UINavigationController
            
            if !userID.isEmpty {
                self.startCall(groupID: "", userIDs: [userID], callingType: type)
            } else if !groupID.isEmpty {
                guard let pushVC = pushVC else { return }
                self.launchCall(type: type, groupID: groupID, pushVC: pushVC, isClassic: false)
            }
        }
        
        var result: [TUIExtensionInfo] = []
        guard let filterVideoCall = param[TUICore_TUIChatExtension_NavigationMoreItem_FilterVideoCall] as? Bool else { return nil }
        
        if !filterVideoCall {
            let videoInfo = TUIExtensionInfo()
            videoInfo.weight = 200
            videoInfo.icon = TUICallKitCommon.getBundleImage(name: "video_call") ?? UIImage()
            videoInfo.onClicked = { param in
                onClick(param, .video)
            }
            result.append(videoInfo)
        }
        
        guard let filterAudioCall = param[TUICore_TUIChatExtension_NavigationMoreItem_FilterAudioCall] as? Bool else { return nil }
        if !filterAudioCall {
            let audioInfo = TUIExtensionInfo()
            audioInfo.weight = 100
            audioInfo.icon = TUICallKitCommon.getBundleImage(name: "audio_call") ?? UIImage()
            audioInfo.onClicked = { param in
                onClick(param, .audio)
            }
            result.append(audioInfo)
        }
        return result
    }
    
    func getInputViewMoreItemExtensionForClassicChat(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
        guard let param = param else { return nil }
        
        var result: [TUIExtensionInfo] = []
        guard let filterVideoCall = param[TUICore_TUIChatExtension_InputViewMoreItem_FilterVideoCall] as? Bool else { return nil }
        
        if !filterVideoCall {
            let videoInfo = TUIExtensionInfo()
            videoInfo.weight = 600
            videoInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVideoCall")
            videoInfo.icon = TUICoreDefineConvert.getTUICoreBundleThemeImage(imageKey: "service_more_video_call_img",
                                                                             defaultImageName: "more_video_call")
            videoInfo.onClicked = { param in
                guard let param = param as? [String: Any] else { return }
                self.doResponseInputViewExtension(param: param, type: .video, isClassic: true)
            }
            result.append(videoInfo)
        }
        
        guard let filterAudioCall = param[TUICore_TUIChatExtension_InputViewMoreItem_FilterAudioCall] as? Bool else { return nil }
        if !filterAudioCall {
            let audioInfo = TUIExtensionInfo()
            audioInfo.weight = 500
            audioInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVoiceCall")
            audioInfo.icon = TUICoreDefineConvert.getTUICoreBundleThemeImage(imageKey: "service_more_voice_call_img",
                                                                             defaultImageName: "more_voice_call")
            audioInfo.onClicked = { param in
                guard let param = param as? [String: Any] else { return }
                self.doResponseInputViewExtension(param: param, type: .audio, isClassic: true)
            }
            result.append(audioInfo)
        }
        return result
    }
    
    func getFriendProfileActionMenuExtensionForClassicContact(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
        guard let param = param else { return nil }
        
        var result: [TUIExtensionInfo] = []
        guard let filterVideoCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterVideoCall] as? Bool else { return nil }
        if !filterVideoCall {
            let videoInfo = TUIExtensionInfo()
            videoInfo.weight = 200
            videoInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVideoCall")
            videoInfo.onClicked = {[weak self] param in
                guard let self = self else { return }
                guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return }
                if !userID.isEmpty {
                    self.startCall(groupID: "", userIDs: [userID], callingType: .video)
                }
            }
            result.append(videoInfo)
        }
        
        guard let filterAudioCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterAudioCall] as? Bool else { return nil }
        if !filterAudioCall {
            let audioInfo = TUIExtensionInfo()
            audioInfo.weight = 100
            audioInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVoiceCall")
            audioInfo.onClicked = {[weak self] param in
                guard let self = self else { return }
                guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return }
                if !userID.isEmpty {
                    self.startCall(groupID: "", userIDs: [userID], callingType: .audio)
                }
            }
            result.append(audioInfo)
        }
        return result
    }
    
    func getFriendProfileActionMenuExtensionForMinimalistContact(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
        guard let param = param else { return nil }
        
        var result: [TUIExtensionInfo] = []
        guard let filterVideoCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterVideoCall] as? Bool else { return nil }
        if !filterVideoCall {
            let videoInfo = TUIExtensionInfo()
            videoInfo.weight = 100
            videoInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist,
                                                                     defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_video")) ?? UIImage())
            videoInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitVideo")
            videoInfo.onClicked = {[weak self] param in
                guard let self = self else { return }
                guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return }
                if !userID.isEmpty {
                    self.startCall(groupID: "", userIDs: [userID], callingType: .video)
                }
            }
            result.append(videoInfo)
        }
        
        guard let filterAudioCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterAudioCall] as? Bool else { return nil }
        if !filterAudioCall {
            let audioInfo = TUIExtensionInfo()
            audioInfo.weight = 200
            audioInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist,
                                                                     defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_audio")) ?? UIImage())
            audioInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitAudio")
            audioInfo.onClicked = {[weak self] param in
                guard let self = self else { return }
                guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return }
                if !userID.isEmpty {
                    self.startCall(groupID: "", userIDs: [userID], callingType: .audio)
                }
            }
            result.append(audioInfo)
        }
        return result
    }
    
    func getGroupInfoCardActionMenuExtensionForMinimalistGroup(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
        guard let param = param else { return nil }
        
        var result: [TUIExtensionInfo] = []
        guard let filterVideoCall = param[TUICore_TUIContactExtension_GroupInfoCardActionMenu_FilterVideoCall] as? Bool else { return nil }
        if !filterVideoCall {
            let videoInfo = TUIExtensionInfo()
            videoInfo.weight = 100
            videoInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist,
                                                                     defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_video")) ?? UIImage())
            videoInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitVideo")
            videoInfo.onClicked = {[weak self] param in
                guard let self = self else { return }
                guard let pushVC = param[TUICore_TUIContactExtension_GroupInfoCardActionMenu_PushVC] as? UINavigationController else { return }
                guard let groupID = param[TUICore_TUIContactExtension_GroupInfoCardActionMenu_GroupID] as? String else { return }
                if !groupID.isEmpty {
                    self.launchCall(type: .video, groupID: groupID, pushVC: pushVC, isClassic: false)
                }
            }
            result.append(videoInfo)
        }
        
        guard let filterAudioCall = param[TUICore_TUIContactExtension_GroupInfoCardActionMenu_FilterAudioCall] as? Bool else { return nil }
        if !filterAudioCall {
            let audioInfo = TUIExtensionInfo()
            audioInfo.weight = 200
            audioInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist,
                                                                     defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_audio")) ?? UIImage())
            audioInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitAudio")
            audioInfo.onClicked = {[weak self] param in
                guard let self = self else { return }
                guard let pushVC = param[TUICore_TUIContactExtension_GroupInfoCardActionMenu_PushVC] as? UINavigationController else { return }
                guard let groupID = param[TUICore_TUIContactExtension_GroupInfoCardActionMenu_GroupID] as? String else { return }
                if !groupID.isEmpty {
                    self.launchCall(type: .audio, groupID: groupID, pushVC: pushVC, isClassic: false)
                }
            }
            result.append(audioInfo)
        }
        return result
    }
    
}
