//
//  ContactChatViewController.swift
//  Qmera
//
//  Created by Yayan Dwi on 22/09/21.
//

import UIKit
import FMDB
import NotificationBannerSwift
import Toast_Swift

class ContactChatViewController: UITableViewController {
    
    deinit {
        print(#function, ">>>> TADAA")
        NotificationCenter.default.removeObserver(self)
    }
    
    var isChooser: ((String, String) -> ())?
    
    var isAdmin: Bool = false
    
    var chats: [Chat] = []
    
    var contacts: [User] = []
    
    var groups: [Group] = []
    
    var groupMap: [String:Int] = [:]
    
    var searchController: UISearchController!
    
    var segment: UISegmentedControl!
    
    var fillteredData: [Any] = []
    
    var isSearchBarEmpty: Bool {
        return searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }
    
    var isFilltering: Bool {
        return !isSearchBarEmpty
    }
    
    var noData = false
    
    func filterContentForSearchText(_ searchText: String) {
        if !searchText.isEmpty {
            switch segment.selectedSegmentIndex {
            case 1:
                Utils.inTabChats = false
                fillteredData = self.contacts.filter { $0.fullName.lowercased().contains(searchText.lowercased()) }
            case 2:
                Utils.inTabChats = false
                fillteredData = self.groups.filter { $0.name.lowercased().contains(searchText.lowercased()) }
            default:
                Utils.inTabChats = true
                fillteredData = self.chats.filter { $0.name.lowercased().contains(searchText.lowercased()) || $0.messageText.lowercased().contains(searchText.lowercased()) }
            }
        }
        tableView.reloadData()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let me = UserDefaults.standard.string(forKey: "me")!
        Database.shared.database?.inTransaction({ fmdb, rollback in
            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME, LAST_NAME, IMAGE_ID, USER_TYPE from BUDDY where F_PIN = '\(me)'"), cursor.next() {
                isAdmin = cursor.string(forColumnIndex: 3) == "23" || cursor.string(forColumnIndex: 3) == "24"
                cursor.close()
            }
        })
        
        //        navigationController?.navigationBar.prefersLargeTitles = true
        
        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel".localized(), style: .plain, target: self, action: #selector(cancel(sender:)))
        
        let childrenMenu : [UIAction] = [
            UIAction(title: "Create Group".localized(), image: UIImage(systemName: "person.and.person"), handler: {[weak self](_) in
                let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "createGroupNav") as! UINavigationController
                let vc = controller.topViewController as! GroupCreateViewController
                vc.isDismiss = { id in
                    self?.groupMap.removeAll()
                    let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "groupDetailView") as! GroupDetailViewController
                    controller.data = id
                    self?.navigationController?.show(controller, sender: nil)
                }
                self?.navigationController?.present(controller, animated: true, completion: nil)
            }),
            UIAction(title: "Add Friends".localized(), image: UIImage(systemName: "person.badge.plus"), handler: {[weak self](_) in
                let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "addFriendNav") as! UINavigationController
                if let vc = controller.viewControllers.first as? AddFriendTableViewController {
                    vc.isDismiss = {
                        self?.getContacts {
                            DispatchQueue.main.async {
                                self?.tableView.reloadData()
                            }
                        }
                    }
                }
                self?.navigationController?.present(controller, animated: true, completion: nil)
            }),
//            UIAction(title: "Configure Email", image: UIImage(systemName: "mail"), handler: {[weak self](_) in
//
//            }),
            UIAction(title: "Favorite Messages".localized(), image: UIImage(systemName: "star"), handler: {[weak self](_) in
                let editorStaredVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "staredVC") as! EditorStarMessages
                self?.navigationController?.show(editorStaredVC, sender: nil)
            }),
        ]
        //debug only
//        isAdmin = true
//        if(isAdmin){
//            childrenMenu.append(UIAction(title: "Broadcast Message".localized(), image: UIImage(systemName: "envelope.open"), handler: {[weak self](_) in
//                let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "broadcastNav")
//                controller.modalPresentationStyle = .fullScreen
//                self?.navigationController?.present(controller, animated: true, completion: nil)
//            }))
//            childrenMenu.append(UIAction(title: "Live Streaming".localized(), image: UIImage(systemName: "video.bubble.left"), handler: {[weak self](_) in
//                let navigationController = UINavigationController(rootViewController: QmeraCreateStreamingViewController())
//                navigationController.modalPresentationStyle = .fullScreen
//                navigationController.navigationBar.tintColor = .white
//                navigationController.navigationBar.barTintColor = .mainColor
//                navigationController.navigationBar.isTranslucent = false
//                navigationController.navigationBar.overrideUserInterfaceStyle = .dark
//                navigationController.navigationBar.barStyle = .black
//                let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white]
//                UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
//                let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
//                navigationController.navigationBar.titleTextAttributes = textAttributes
//                navigationController.view.backgroundColor = .mainColor
//                self?.navigationController?.present(navigationController, animated: true, completion: nil)
//            }))
//        }
        
        let menu = UIMenu(title: "", children: childrenMenu)
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: nil, image: UIImage(systemName: "ellipsis"), primaryAction: .none, menu: menu)
        
        searchController = UISearchController(searchResultsController: nil)
        searchController.delegate = self
        searchController.searchResultsUpdater = self
        searchController.searchBar.autocapitalizationType = .none
        searchController.searchBar.delegate = self
        searchController.searchBar.barTintColor = .secondaryColor
        searchController.searchBar.searchTextField.backgroundColor = .secondaryColor
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.setMagnifyingGlassColorTo(color: .mainColor)
        searchController.searchBar.tintColor = .mainColor
        searchController.searchBar.searchTextField.attributedPlaceholder = NSAttributedString(string: "Search".localized(), attributes: [NSAttributedString.Key.foregroundColor: UIColor.gray])
        
        
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = false
        
        definesPresentationContext = true
        
        segment = UISegmentedControl(items: ["Chats".localized(), "Contacts".localized(), "Groups".localized()])
        segment.sizeToFit()
        segment.selectedSegmentIndex = 0
        segment.addTarget(self, action: #selector(segmentChanged(sender:)), for: .valueChanged)
        segment.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12.0)], for: .normal)
        Utils.inTabChats = true
        
        NotificationCenter.default.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: "onMessageChat"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(onReceiveMessage(notification:)), name: NSNotification.Name(rawValue: "onReceiveChat"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(onReload(notification:)), name: NSNotification.Name(rawValue: "onMember"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(onReload(notification:)), name: NSNotification.Name(rawValue: "onUpdatePersonInfo"), object: nil)
        
        tableView.tableHeaderView = segment
        tableView.tableFooterView = UIView()
        
        pullBuddy()
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16.0), NSAttributedString.Key.foregroundColor: UIColor.white]
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.backgroundColor = UIColor.mainColor
        navBarAppearance.titleTextAttributes = attributes
        navigationController?.navigationBar.standardAppearance = navBarAppearance
        navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
//        removeAllData()
        getData()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        Utils.inTabChats = false
    }
    
    override func viewDidAppear(_ animated: Bool) {
        if isChooser != nil {
            self.navigationController?.navigationBar.topItem?.title = "Forward Messages".localized()
            self.navigationController?.navigationBar.setNeedsLayout()
        } else {
            self.navigationController?.navigationBar.topItem?.title = "Start Conversation".localized()
            self.navigationController?.navigationBar.setNeedsLayout()
        }
        DispatchQueue.global().async {
            self.getOpenGroups(listGroups: self.groups, completion: { g in
                DispatchQueue.main.async {
                    for og in g {
                        if self.groups.first(where: { $0.id == og.id }) == nil {
                            self.groups.append(og)
                        }
                    }
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                }
            })
        }
        if segment.selectedSegmentIndex == 0 {
            Utils.inTabChats = true
        }
    }
    
//    func removeAllData() {
//        groups.removeAll()
//        groupMap.removeAll()
//        chats.removeAll()
//        tableView.reloadData()
//    }
    
    @objc func onReload(notification: NSNotification) {
        let data:[AnyHashable : Any] = notification.userInfo!
        if data["member"] as? String == UserDefaults.standard.string(forKey: "me") {
            DispatchQueue.main.async {
                self.getData()
            }
        } else if data["state"] as? Int == 99 {
            print("MASUK 99")
            DispatchQueue.main.async {
                self.getData()
            }
        }
    }
    
    @objc func onReceiveMessage(notification: NSNotification) {
        DispatchQueue.main.async { [self] in
            let data:[AnyHashable : Any] = notification.userInfo!
            if let dataMessage = data["message"] as? TMessage {
                let chatData = dataMessage.mBodies
                if chatData[CoreMessage_TMessageKey.IS_CALL_CENTER] == "0" {
                    var indexChat: Int?
                    if chatData[CoreMessage_TMessageKey.MESSAGE_SCOPE_ID] == "3" && chatData[CoreMessage_TMessageKey.F_PIN] != User.getMyPin() {
                        indexChat = chats.firstIndex(where: { $0.fpin == chatData[CoreMessage_TMessageKey.F_PIN] })
                    } else if chatData[CoreMessage_TMessageKey.MESSAGE_SCOPE_ID] == "4" && chatData[CoreMessage_TMessageKey.F_PIN] != User.getMyPin() {
                        indexChat = chats.firstIndex(where: { (chatData[CoreMessage_TMessageKey.CHAT_ID] ?? "").isEmpty ? $0.pin == chatData[CoreMessage_TMessageKey.L_PIN] : $0.pin == chatData[CoreMessage_TMessageKey.CHAT_ID] })
                    }
                    let newChat = Chat.getData(messageId: chatData[CoreMessage_TMessageKey.MESSAGE_ID] ?? "")
                    if newChat.count > 0 {
                        if indexChat != nil {
                            chats[0] = newChat[0]
                            let indexPathToMove = IndexPath(row: indexChat!, section: 0)
                            let indexPathNewPosition = IndexPath(row: 0, section: 0)
                            tableView.performBatchUpdates({
                                tableView.moveRow(at: indexPathToMove, to: indexPathNewPosition)
                            }, completion: nil)
                            tableView.beginUpdates()
                            tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .none)
                            tableView.endUpdates()
                        } else {
                            if noData {
                                chats.insert(newChat[0], at: 0)
                                tableView.reloadData()
                            } else {
                                chats.insert(newChat[0], at: 0)
                                tableView.beginUpdates()
                                tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .none)
                                tableView.endUpdates()
                            }
                        }
                    }
                }
            }
        }
    }
    
    @objc func onStatusChat(notification: NSNotification) {
        DispatchQueue.main.async { [self] in
            let data:[AnyHashable : Any] = notification.userInfo!
            if let dataMessage = data["message"] as? TMessage {
                let chatData = dataMessage.mBodies
                let indexChat = chats.firstIndex(where: { (chatData[CoreMessage_TMessageKey.MESSAGE_ID] ?? "").contains(",") ? $0.messageId == (chatData[CoreMessage_TMessageKey.MESSAGE_ID]!).components(separatedBy: ",")[1]  : $0.messageId == chatData[CoreMessage_TMessageKey.MESSAGE_ID] })
                if indexChat != nil {
                    tableView.beginUpdates()
                    tableView.reloadRows(at: [IndexPath(row: indexChat!, section: 0)], with: .none)
                    tableView.endUpdates()
                }
            }
        }
    }
    
    @objc func add(sender: Any) {
        
    }
    
    @objc func cancel(sender: Any) {
        navigationController?.dismiss(animated: true, completion: nil)
    }
    
    @objc func segmentChanged(sender: Any) {
        filterContentForSearchText(searchController.searchBar.text!)
    }
    
    // MARK: - Data source
    
    func getData() {
        getChats {
            self.getContacts {
                self.getGroups { g1 in
                    self.groupMap.removeAll()
                    self.groups = g1
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                }
            }
        }
    }
    
    func getChats(completion: @escaping ()->()) {
        DispatchQueue.global().async {
            self.chats = Chat.getData()
            completion()
        }
    }
    
    private func getContacts(completion: @escaping ()->()) {
        self.contacts.removeAll()
        DispatchQueue.global().async {
            Database.shared.database?.inTransaction({ (fmdb, rollback) in
                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, image_id, official_account, user_type FROM BUDDY where f_pin <> '\(UserDefaults.standard.string(forKey: "me")!)' order by 5 desc, 2 collate nocase asc") {
                    while cursorData.next() {
                        let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
                                        firstName: cursorData.string(forColumnIndex: 1) ?? "",
                                        lastName: cursorData.string(forColumnIndex: 2) ?? "",
                                        thumb: cursorData.string(forColumnIndex: 3) ?? "",
                                        userType: cursorData.string(forColumnIndex: 5) ?? "")
                        if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
                            continue
                        }
                        user.official = cursorData.string(forColumnIndex: 4) ?? ""
                        if !self.contacts.contains(where: {$0.pin == user.pin}) {
                            self.contacts.append(user)
                        }
                    }
                    cursorData.close()
                }
                completion()
            })
        }
    }
    
    private func getGroupRecursive(fmdb: FMDatabase, id: String = "", parent: String = "") -> [Group] {
        var data: [Group] = []
        var query = "select g.group_id, g.f_name, g.image_id, g.quote, g.created_by, g.created_date, g.parent, g.group_type, g.is_open, g.official, g.is_education, g.level from GROUPZ g where "
        if id.isEmpty {
            query += "g.parent = '\(parent)'"
        } else {
            query += "g.group_id = '\(id)'"
        }
        query += "order by 10 desc"
        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
            while cursor.next() {
                let group = Group(
                    id: cursor.string(forColumnIndex: 0) ?? "",
                    name: cursor.string(forColumnIndex: 1) ?? "",
                    profile: cursor.string(forColumnIndex: 2) ?? "",
                    quote: cursor.string(forColumnIndex: 3) ?? "",
                    by: cursor.string(forColumnIndex: 4) ?? "",
                    date: cursor.string(forColumnIndex: 5) ?? "",
                    parent: cursor.string(forColumnIndex: 6) ?? "",
                    chatId: "",
                    groupType: cursor.string(forColumnIndex: 7) ?? "",
                    isOpen: cursor.string(forColumnIndex: 8) ?? "",
                    official: cursor.string(forColumnIndex: 9) ?? "",
                    isEducation: cursor.string(forColumnIndex: 10) ?? "",
                    level: cursor.string(forColumnIndex: 11) ?? "")
                
                if group.chatId.isEmpty {
                    let lounge = Group(id: group.id, name: "Lounge".localized(), profile: "", quote: group.quote, by: group.by, date: group.date, parent: group.id, chatId: group.chatId, groupType: group.groupType, isOpen: group.isOpen, official: group.official, isEducation: group.isEducation, isLounge: true, level: group.level != "-1" ? group.level : "2")
                    group.childs.append(lounge)
                }
                
                if let topicCursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where group_id = '\(group.id)'") {
                    while topicCursor.next() {
                        let topic = Group(id: group.id,
                                          name: topicCursor.string(forColumnIndex: 1) ?? "",
                                          profile: topicCursor.string(forColumnIndex: 2) ?? "",
                                          quote: group.quote,
                                          by: group.by,
                                          date: group.date,
                                          parent: group.id,
                                          chatId: topicCursor.string(forColumnIndex: 0) ?? "",
                                          groupType: group.groupType,
                                          isOpen: group.isOpen,
                                          official: group.official,
                                          isEducation: group.isEducation,
                                          level: group.level != "-1" ? group.level : "2")
                        group.childs.append(topic)
                    }
                    topicCursor.close()
                }
                
                if !group.id.isEmpty {
//                    if group.official == "1" {
//                        let idMe = UserDefaults.standard.string(forKey: "me") as String?
//                        if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
////                            if cursorUser.string(forColumnIndex: 0) == "23" || cursorUser.string(forColumnIndex: 0) == "24" {
////                                group.childs.append(contentsOf: getGroupRecursive(fmdb: fmdb, parent: group.id))
////                            }
//                            group.childs.append(contentsOf: getGroupRecursive(fmdb: fmdb, parent: group.id))
//                            cursorUser.close()
//                        }
//                    } else if group.official != "1"{
//                        group.childs.append(contentsOf: getGroupRecursive(fmdb: fmdb, parent: group.id))
//                    }
                    group.childs.append(contentsOf: getGroupRecursive(fmdb: fmdb, parent: group.id))
//                    group.childs = group.childs.sorted(by: { $0.name < $1.name })
//                    let dataLounge = group.childs.filter({$0.name == "Lounge".localized()})
//                    group.childs = group.childs.filter({ $0.name != "Lounge".localized() })
//                    group.childs.insert(contentsOf: dataLounge, at: 0)
                }
                data.append(group)
            }
            cursor.close()
        }
        return data
    }
    
    private func getOpenGroups(listGroups: [Group], completion: @escaping ([Group]) -> ()) {
        if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getOpenGroups(p_account: "1,2,3,5,6,7", offset: "0", search: "")) {
            var dataGroups: [Group] = []
            if (response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "00") {
                let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
                if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [[String: Any?]] {
                    for dataJson in json {
                        let group = Group(
                            id: dataJson[CoreMessage_TMessageKey.GROUP_ID] as? String ?? "",
                            name: dataJson[CoreMessage_TMessageKey.GROUP_NAME] as? String ?? "",
                            profile: dataJson[CoreMessage_TMessageKey.THUMB_ID] as? String ?? "",
                            quote: dataJson[CoreMessage_TMessageKey.QUOTE] as? String ?? "",
                            by: dataJson[CoreMessage_TMessageKey.BLOCK] as? String ?? "",
                            date: "",
                            parent: "",
                            chatId: "",
                            groupType: "NOTJOINED",
                            isOpen: dataJson[CoreMessage_TMessageKey.IS_OPEN] as? String ?? "",
                            official: "0",
                            isEducation: "")
                        dataGroups.append(group)
                    }
                }
            } else {
                DispatchQueue.main.async {
                    self.groups.removeAll()
                    self.groups.append(contentsOf: listGroups)
                    self.tableView.reloadData()
                }
            }
            completion(dataGroups)
        }
    }
    
    private func getGroups(id: String = "", parent: String = "", completion: @escaping ([Group]) -> ()) {
        DispatchQueue.global().async {
            Database.shared.database?.inTransaction({ fmdb, rollback in
                completion(self.getGroupRecursive(fmdb: fmdb, id: id, parent: parent))
            })
        }
    }
    
    private func pullBuddy() {
        if let me = UserDefaults.standard.string(forKey: "me") {
            DispatchQueue.global().async {
                let _ = Nexilis.write(message: CoreMessage_TMessageBank.getBatchBuddiesInfos(p_f_pin: me, last_update: 0))
            }
        }
    }
    
    private func joinOpenGroup(groupId: String, flagMember: String = "0", completion: @escaping (Bool) -> ()) {
        DispatchQueue.global().async {
            var result: Bool = false
            let idMe = UserDefaults.standard.string(forKey: "me") as String?
            if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddGroupMember(p_group_id: groupId, p_member_pin: idMe!, p_position: "0")), response.isOk() {
                result = true
            }
            completion(result)
        }
    }
    
}

// MARK: - Table view data source

extension ContactChatViewController {
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if noData {
            return
        }
        tableView.deselectRow(at: indexPath, animated: true)
        switch segment.selectedSegmentIndex {
        case 0:
            let data: Chat
            if isFilltering {
                data = fillteredData[indexPath.row] as! Chat
            } else {
                data = chats[indexPath.row]
            }
            if let chooser = isChooser {
                var exblock = User.getDataCanNil(pin: data.pin)?.ex_block
                exblock = exblock == nil ? "0" : exblock!.isEmpty ? "0" : exblock!
                if exblock != "0" {
                    if exblock == "1" {
                        self.view.makeToast("You blocked this user".localized())
                    } else {
                        self.view.makeToast("You have been blocked by this user".localized())
                    }
                    return
                }
                if data.pin == "-999"{
                    return
                }
                chooser(data.messageScope, data.pin)
                dismiss(animated: true, completion: nil)
                return
            }
            if data.messageScope == "3" {
                let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
                editorPersonalVC.hidesBottomBarWhenPushed = true
                editorPersonalVC.unique_l_pin = data.pin
                navigationController?.show(editorPersonalVC, sender: nil)
            } else {
                groupMap.removeAll()
                let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
                editorGroupVC.hidesBottomBarWhenPushed = true
                editorGroupVC.unique_l_pin = data.pin
                navigationController?.show(editorGroupVC, sender: nil)
            }
        case 1:
            let data: User
            if isFilltering {
                data = fillteredData[indexPath.row] as! User
            } else {
                data = contacts[indexPath.row]
            }
            if let chooser = isChooser {
                var exblock = User.getDataCanNil(pin: data.pin)?.ex_block
                exblock = exblock == nil ? "0" : exblock!.isEmpty ? "0" : exblock!
                if exblock != "0" {
                    if exblock == "1" {
                        self.view.makeToast("You blocked this user".localized())
                    } else {
                        self.view.makeToast("You have been blocked by this user".localized())
                    }
                    return
                }
                chooser("3", data.pin)
                dismiss(animated: true, completion: nil)
                return
            }
            let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
            editorPersonalVC.hidesBottomBarWhenPushed = true
            editorPersonalVC.unique_l_pin = data.pin
            navigationController?.show(editorPersonalVC, sender: nil)
        case 2:
            expandCollapseGroup(tableView: tableView, indexPath: indexPath)
        default:
            let data = contacts[indexPath.row]
            let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
            editorPersonalVC.hidesBottomBarWhenPushed = true
            editorPersonalVC.unique_l_pin = data.pin
            navigationController?.show(editorPersonalVC, sender: nil)
        }
    }
    
    func expandCollapseGroup(tableView: UITableView, indexPath: IndexPath) {
        let group: Group
        if isFilltering {
            if indexPath.row == 0 {
                group = fillteredData[indexPath.section] as! Group
            } else {
                group = (fillteredData[indexPath.section] as! Group).childs[indexPath.row - 1]
            }
        } else {
            if indexPath.row == 0 {
                group = groups[indexPath.section]
            } else {
                group = groups[indexPath.section].childs[indexPath.row - 1]
            }
        }
        group.isSelected = !group.isSelected
        if !group.isSelected{
            var sects = 0
            var sect = indexPath.section
            var id = group.id
            if let _ = groupMap[id] {
                var loooop = true
                repeat {
                    let c = sect + 1
                    if isFilltering {
                        if let o = self.fillteredData[c] as? Group {
                            if o.parent == id {
                                sects = sects + 1
                                sect = c
                                id = o.id
                                (self.fillteredData[c] as! Group).isSelected = false
                                self.groupMap.removeValue(forKey: (self.fillteredData[c] as! Group).id)
                            }
                            else {
                                loooop = false
                            }
                        }
                    }
                    else {
                        if c < self.groups.count && self.groups[c].parent == id {
                            sects = sects + 1
                            sect = c
                            id = self.groups[c].id
                            self.groups[c].isSelected = false
                            self.groupMap.removeValue(forKey: self.groups[c].id)
                        }
                        else {
                            loooop = false
                        }
                    }
                } while(loooop)
            }
            for i in stride(from: sects, to: 0, by: -1){
                if isFilltering {
                    self.fillteredData.remove(at: indexPath.section + i)
                }
                else {
                    self.groups.remove(at: indexPath.section + i)
                }
            }
            groupMap.removeValue(forKey: group.id)
        }
        if group.groupType == "NOTJOINED" {
            let alert = UIAlertController(title: "Do you want to join this group?".localized(), message: "Groups : \(group.name)\nMembers: \(group.by)".localized(), preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
            alert.addAction(UIAlertAction(title: "Join".localized(), style: .default, handler: {(_) in
                self.joinOpenGroup(groupId: group.id, completion: { result in
                    if result {
                        DispatchQueue.main.async {
                            self.groupMap.removeAll()
                            let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
                            editorGroupVC.hidesBottomBarWhenPushed = true
                            editorGroupVC.unique_l_pin = group.id
                            self.navigationController?.show(editorGroupVC, sender: nil)
                        }
                    }
                })
            }))
            self.present(alert, animated: true, completion: nil)
            return
        }
        if group.childs.count == 0 {
            Database.shared.database?.inTransaction({ (fmdb, rollback) in
                let idMe = UserDefaults.standard.string(forKey: "me") as String?
                if let cursorMember = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from GROUPZ_MEMBER where group_id = '\(group.id)' and f_pin = '\(idMe!)'"), cursorMember.next() {
                    let groupId = group.chatId.isEmpty ? group.id : group.chatId
                    if let chooser = isChooser {
                        chooser("4", groupId)
                        dismiss(animated: true, completion: nil)
                        return
                    }
                    self.groupMap.removeAll()
                    let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
                    editorGroupVC.hidesBottomBarWhenPushed = true
                    editorGroupVC.unique_l_pin = groupId
                    navigationController?.show(editorGroupVC, sender: nil)
                    cursorMember.close()
                } else {
                    self.view.makeToast("You are not a member of this group".localized(), duration: 0.5)
                }
            })
        } else {
            if indexPath.row == 0 {
                tableView.reloadData()
            } else {
                getGroups(id: group.id) { g in
                    DispatchQueue.main.async {
                        print("index path section: \(indexPath.section)")
                        print("index path row: \(indexPath.row)")
//                            print("index path item: \(indexPath.item)")
                        if self.isFilltering {
//                                self.fillteredData.remove(at: indexPath.section)
                            if self.fillteredData[indexPath.section] is Group {
                                self.groupMap[(self.fillteredData[indexPath.section] as! Group).id] = 1
                                self.fillteredData.insert(contentsOf: g, at: indexPath.section + 1)
                            }
                        } else {
//                                self.groups.remove(at: indexPath.section)
                            self.groupMap[self.groups[indexPath.section].id] = 1
                            self.groups.insert(contentsOf: g, at: indexPath.section + 1)
                        }
                        print("groupMap: \(self.groupMap)")
                        tableView.reloadData()
                        
                        self.expandCollapseGroup(tableView: tableView, indexPath: IndexPath(row: 0, section: indexPath.section + 1))
                    }
                }
            }
        }
    }
    
}

extension ContactChatViewController {
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        if isFilltering {
            if segment.selectedSegmentIndex == 2 {
                return fillteredData.count
            }
            return 1
        } else {
            if segment.selectedSegmentIndex == 2 {
                return groups.count
            }
            return 1
        }
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        var value = 0
        if isFilltering {
            if segment.selectedSegmentIndex == 2, let groups = fillteredData as? [Group] {
                let group = groups[section]
                if group.isSelected {
                    if let _ = groupMap[group.id] {
                        value = 1
                    }
                    else {
                        value = group.childs.count + 1
                    }
                } else {
                    value = 1
                }
            } else {
                value = fillteredData.count
            }
            return value
        }
        switch segment.selectedSegmentIndex {
        case 0:
            value = chats.count
        case 1:
            value = contacts.count
        case 2:
            let group = groups[section]
            if group.isSelected {
                if let _ = groupMap[group.id] {
                    value = 1
                }
                else {
                    value = group.childs.count + 1
                }
            } else {
                value = 1
            }
        default:
            value = chats.count
        }
        if value == 0 {
            noData = true
            value = 1
            tableView.separatorStyle = .none
        } else {
            noData = false
            tableView.separatorStyle = .singleLine
        }
        return value
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell: UITableViewCell!
        switch segment.selectedSegmentIndex {
        case 0:
            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierChat", for: indexPath)
            let content = cell.contentView
            if content.subviews.count > 0 {
                content.subviews.forEach { $0.removeFromSuperview() }
            }
            if noData {
                let labelNochat = UILabel()
                labelNochat.text = "There are no conversations".localized()
                labelNochat.font = .systemFont(ofSize: 13)
                labelNochat.textColor = .black
                content.addSubview(labelNochat)
                labelNochat.anchor(centerX: content.centerXAnchor, centerY: content.centerYAnchor)
                cell.backgroundColor = .clear
                cell.selectionStyle = .none
                return cell
            }
            let data: Chat
            if isFilltering {
                data = fillteredData[indexPath.row] as! Chat
            } else {
                if chats.count == 0 {
                    let labelNochat = UILabel()
                    labelNochat.text = "There are no conversations".localized()
                    labelNochat.font = .systemFont(ofSize: 13)
                    labelNochat.textColor = .black
                    content.addSubview(labelNochat)
                    labelNochat.anchor(centerX: content.centerXAnchor, centerY: content.centerYAnchor)
                    cell.backgroundColor = .clear
                    cell.selectionStyle = .none
                    return cell
                }
                data = chats[indexPath.row]
            }
            let imageView = UIImageView()
            content.addSubview(imageView)
            imageView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                imageView.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 10.0),
                imageView.topAnchor.constraint(equalTo: content.topAnchor, constant: 10.0),
                imageView.bottomAnchor.constraint(equalTo: content.bottomAnchor, constant: -25.0),
                imageView.widthAnchor.constraint(equalToConstant: 40.0),
                imageView.heightAnchor.constraint(equalToConstant: 40.0)
            ])
            if data.profile.isEmpty && data.pin != "-999" {
                if data.messageScope == "3" {
                    imageView.image = UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
                } else {
                    imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
                }
            } else {
                if Utils.getIconDock() != nil {
                    let dataImage = try? Data(contentsOf: URL(string: Utils.getUrlDock()!)!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
                    if dataImage != nil {
                        getImage(name: data.profile, placeholderImage: UIImage(data: dataImage!), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
                            imageView.image = image
                        })
                    }
                } else {
                    getImage(name: data.profile, placeholderImage: UIImage(named: data.pin == "-999" ? "pb_button" : data.messageScope == "3" ? "Profile---Purple" : "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
                        imageView.image = image
                    })
                }
            }
            let titleView = UILabel()
            content.addSubview(titleView)
            titleView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                titleView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 10.0),
                titleView.topAnchor.constraint(equalTo: content.topAnchor, constant: 10.0),
                titleView.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -40.0),
            ])
            titleView.text = data.name
            titleView.font = UIFont.systemFont(ofSize: 14, weight: .medium)
            
            let messageView = UILabel()
            content.addSubview(messageView)
            messageView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                messageView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 10.0),
                messageView.topAnchor.constraint(equalTo: titleView.bottomAnchor, constant: 5.0),
                messageView.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -40.0),
            ])
            messageView.textColor = .gray
            let text = Utils.previewMessageText(chat: data)
            let idMe = UserDefaults.standard.string(forKey: "me") as String?
            if let attributeText = text as? NSMutableAttributedString {
                if data.fpin == idMe {
                    if data.lock == "1" {
                        messageView.attributedText = ("🚫 _"+"You were deleted this message".localized()+"_").richText()
                    } else {
                        let stringMessage = NSMutableAttributedString(string: "")
                        let imageStatus = NSTextAttachment()
                        let status = getRealStatus(messageId: data.messageId)
                        if (status == "1" || status == "2" ) {
                            imageStatus.image = UIImage(named: "checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
                        } else if (status == "3") {
                            imageStatus.image = UIImage(named: "double-checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
                        } else if (status == "8") {
                            imageStatus.image = UIImage(named: "message_status_ack", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal)
                        } else {
                            imageStatus.image = UIImage(named: "double-checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.systemBlue)
                        }
                        imageStatus.bounds = CGRect(x: 0, y: 0, width: 15, height: 15)
                        let imageStatusString = NSAttributedString(attachment: imageStatus)
                        stringMessage.append(imageStatusString)
                        stringMessage.append(NSAttributedString(string: " "))
                        stringMessage.append(attributeText)
                        messageView.attributedText = stringMessage
                    }
                } else {
                    if data.lock == "1" {
                        messageView.attributedText = ("🚫 _"+"This message was deleted".localized()+"_").richText()
                    } else {
                        messageView.attributedText = attributeText
                    }
                }
            }
            messageView.numberOfLines = 2
            
            if data.counter != "0" {
                let viewCounter = UIView()
                content.addSubview(viewCounter)
                viewCounter.translatesAutoresizingMaskIntoConstraints = false
                NSLayoutConstraint.activate([
                    viewCounter.centerYAnchor.constraint(equalTo: content.centerYAnchor),
                    viewCounter.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -20),
                    viewCounter.widthAnchor.constraint(greaterThanOrEqualToConstant: 20),
                    viewCounter.heightAnchor.constraint(equalToConstant: 20)
                ])
                viewCounter.backgroundColor = .systemRed
                viewCounter.layer.cornerRadius = 10
                viewCounter.clipsToBounds = true
                viewCounter.layer.borderWidth = 0.5
                viewCounter.layer.borderColor = UIColor.secondaryColor.cgColor

                let labelCounter = UILabel()
                viewCounter.addSubview(labelCounter)
                labelCounter.translatesAutoresizingMaskIntoConstraints = false
                NSLayoutConstraint.activate([
                    labelCounter.centerYAnchor.constraint(equalTo: viewCounter.centerYAnchor),
                    labelCounter.leadingAnchor.constraint(equalTo: viewCounter.leadingAnchor, constant: 2),
                    labelCounter.trailingAnchor.constraint(equalTo: viewCounter.trailingAnchor, constant: -2),
                ])
                labelCounter.font = UIFont.systemFont(ofSize: 11)
                if Int(data.counter)! > 99 {
                    labelCounter.text = "99+"
                } else {
                    labelCounter.text = data.counter
                }
                labelCounter.textColor = .secondaryColor
                labelCounter.textAlignment = .center
            }
        case 1:
            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierContact", for: indexPath)
            var content = cell.defaultContentConfiguration()
            let data: User
            if isFilltering {
                data = fillteredData[indexPath.row] as! User
            } else {
                if  indexPath.row > contacts.count - 1 {
                    return cell
                }
                data = contacts[indexPath.row]
            }
            content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
            getImage(name: data.thumb, placeholderImage: UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
                content.image = image
            })
            if User.isOfficial(official_account: data.official ?? "") || User.isOfficialRegular(official_account: data.official ?? "") {
                content.attributedText = self.set(image: UIImage(named: "ic_official_flag", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(data.fullName)", size: 15, y: -4, colorText: UIColor.officialColor)
                
            } else if User.isVerified(official_account: data.official ?? "") {
                content.attributedText = self.set(image: UIImage(named: "ic_verified", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(data.fullName)", size: 15, y: -4, colorText: UIColor.verifiedColor)
            }
            else if User.isInternal(userType: data.userType ?? "") {
                content.attributedText = self.set(image: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(data.fullName)", size: 15, y: -4, colorText: UIColor.internalColor)
            } else if User.isCallCenter(userType: data.userType ?? "") {
                let dataCategory = CategoryCC.getDataFromServiceId(service_id: data.ex_offmp!)
                if dataCategory != nil {
                    content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(data.fullName) (\(dataCategory!.service_name))", size: 15, y: -4, colorText: UIColor.ccColor)
                } else {
                    content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(data.fullName)", size: 15, y: -4, colorText: UIColor.ccColor)
                }
            } else {
                content.text = data.fullName
            }
            content.textProperties.font = UIFont.systemFont(ofSize: 14)
            cell.contentConfiguration = content
        case 2:
            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierGroup", for: indexPath)
            var content = cell.defaultContentConfiguration()
            content.textProperties.font = UIFont.systemFont(ofSize: 14)
            let group: Group
            if isFilltering {
                if indexPath.row == 0 {
                    group = fillteredData[indexPath.section] as! Group
                } else {
                    if (fillteredData[indexPath.section] as! Group).childs.count > 0 {
                        group = (fillteredData[indexPath.section] as! Group).childs[indexPath.row - 1]
                    } else {
                        return cell
                    }
                }
            } else {
                if indexPath.row == 0 {
                    if indexPath.section > (groups.count - 1) {
                        return cell
                    }
                    group = groups[indexPath.section]
                } else {
                    group = groups[indexPath.section].childs[indexPath.row - 1]
                }
            }
            if group.official == "1" && group.parent == "" {
                content.attributedText = self.set(image: UIImage(named: "ic_official_flag", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(group.name)", size: 15, y: -4)
            }
            else if group.isOpen == "1" && group.parent == "" {
                if self.traitCollection.userInterfaceStyle == .dark {
                    content.attributedText = self.set(image: UIImage(systemName: "globe")!.withTintColor(.white), with: "  \(group.name)", size: 15, y: -4)
                } else {
                    content.attributedText = self.set(image: UIImage(systemName: "globe")!, with: "  \(group.name)", size: 15, y: -4)
                }
            } else if group.parent == "" {
                if self.traitCollection.userInterfaceStyle == .dark {
                    content.attributedText = self.set(image: UIImage(systemName: "lock.fill")!.withTintColor(.white), with: "  \(group.name)", size: 15, y: -4)
                } else {
                    content.attributedText = self.set(image: UIImage(systemName: "lock.fill")!, with: "  \(group.name)", size: 15, y: -4)
                }
            } else {
                content.text = group.name
            }
            if group.childs.count > 0 {
                let iconName = (group.isSelected) ? "chevron.up.circle" : "chevron.down.circle"
                let imageView = UIImageView(image: UIImage(systemName: iconName))
                imageView.tintColor = .black
                cell.accessoryView = imageView
            }
            else {
                cell.accessoryView = nil
                cell.accessoryType = .none
            }
            content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
            getImage(name: group.profile, placeholderImage: UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
                content.image = image
            }
            cell.contentConfiguration = content
            if !group.level.isEmpty {
                if group.level != "-1" && Int(group.level)! < 7 {
                    cell.contentView.layoutMargins = .init(top: 0.0, left: CGFloat(25 * Int(group.level)!), bottom: 0.0, right: 0)
                } else if Int(group.level)! > 6 {
                    cell.contentView.layoutMargins = .init(top: 0.0, left: CGFloat(25 * (Int(group.level)! - 6)), bottom: 0.0, right: 0)
                }
            }
        default:
            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierContact", for: indexPath)
            var content = cell.defaultContentConfiguration()
            content.text = ""
            cell.contentConfiguration = content
        }
        cell.backgroundColor = .clear
        cell.separatorInset = UIEdgeInsets(top: 0, left: 60.0, bottom: 0, right: 0)
        return cell
    }
    
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 75.0
    }
    
    private func getRealStatus(messageId: String) -> String {
        var status = "1"
        Database.shared.database?.inTransaction({ (fmdb, rollback) in
            if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status, f_pin FROM MESSAGE_STATUS WHERE message_id='\(messageId)'") {
                var listStatus: [Int] = []
                while cursorStatus.next() {
                    listStatus.append(Int(cursorStatus.string(forColumnIndex: 0)!)!)
                }
                cursorStatus.close()
                status = "\(listStatus.min() ?? 2)"
            }
        })
        return status
    }
    
}


extension ContactChatViewController: UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {
    
    func updateSearchResults(for searchController: UISearchController) {
        filterContentForSearchText(searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines))
    }
    
    func set(image: UIImage, with text: String, size: CGFloat, y: CGFloat, colorText: UIColor = UIColor.black) -> NSAttributedString {
        let attachment = NSTextAttachment()
        attachment.image = image
        attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
        let attachmentStr = NSAttributedString(attachment: attachment)
        
        let mutableAttributedString = NSMutableAttributedString()
        mutableAttributedString.append(attachmentStr)
        
        let attributedStringColor = [NSAttributedString.Key.foregroundColor : colorText]
        let textString = NSAttributedString(string: text, attributes: attributedStringColor)
        mutableAttributedString.append(textString)
        
        
        return mutableAttributedString
    }
    
    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
        searchBar.showsCancelButton = true
        let cBtn = searchBar.value(forKey: "cancelButton") as! UIButton
        cBtn.setTitle("Cancel".localized(), for: .normal)
    }
    
    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        searchBar.showsCancelButton = false
    }
    
}
