//
// MIT License
//
// Copyright (c) 2017-2020 MessageKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import InputBarAccessoryView
import MessageKit
import UIKit
import MapKit
// MARK: - TSChatViewController

/// A base class for the example controllers
class TSChatViewController: MessagesViewController, MessagesDataSource {
    // MARK: Internal
    var viewModel:TSAIChatVM = TSAIChatVM()
    
    
    // MARK: - Public properties
    lazy var messageList: [TSChatMessage] = []
    
    private(set) lazy var refreshControl: UIRefreshControl = {
        let control = UIRefreshControl()
        control.addTarget(self, action: #selector(loadMoreMessages), for: .valueChanged)
        return control
    }()
    
    // MARK: Private
    lazy var textMessageSizeCalculator = TSTextLayoutSizeCalculator(layout: self.messagesCollectionView.messagesCollectionViewFlowLayout)
    
    
    lazy var inputBarVC: TSChatInputBarVC = {
        let inputBarVC = TSChatInputBarVC()
        inputBarVC.sendComplete = { [weak self] components in
            guard let self = self else { return }
            sendMessages(components)
            messagesCollectionView.scrollToLastItem(animated: true)
        }
        return inputBarVC
    }()
    
    
    
    lazy var text: UILabel = {
        let textLabel = UILabel.createLabel(text: "Remaining 3 free times")
        return textLabel
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "MessageKit"

        configureMessageCollectionView()
        configureMessageInputBar()
        loadFirstMessages()
        
        
        if viewModel.uiStyle == .chat {
            // 注册通知监听,App死的时候,保存本次聊天记录到本地
            NotificationCenter.default.addObserver(self, selector: #selector(saveChatList), name: .kApplicationWillTerminate, object: nil)
        }
    }
    
    @objc func saveChatList() {
        messageList.remove(at: 0)
        viewModel.updateMessages(msgModels: messageList)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
    }
    
    func loadFirstMessages() {
        //获取消息数量
        self.messageList = viewModel.getHistoryChatMessage()
        self.messagesCollectionView.reloadData()
        self.messagesCollectionView.scrollToLastItem(animated: false)
    }
    
    @objc
    func loadMoreMessages() {
        //获取更多消息数量
        
    }
    
    func configureMessageCollectionView() {
        view.backgroundColor = .clear
        //设置自定义FlowLayout,itemsize等,都在这里控制
        let flowLayout = CustomMessagesFlowLayout()
        flowLayout.sectionInset = UIEdgeInsets(top: 4, left: 0, bottom: 4, right: 0)
    
        messagesCollectionView.collectionViewLayout = flowLayout
        messagesCollectionView.backgroundColor = .clear
        messagesCollectionView.register(TSTextMessageContentCell.self)
        messagesCollectionView.messagesLayoutDelegate = self
        messagesCollectionView.messagesDisplayDelegate = self
        messagesCollectionView.messagesDataSource = self
        messagesCollectionView.messageCellDelegate = self
        messagesCollectionView.clipsToBounds = true
        scrollsToLastItemOnKeyboardBeginsEditing = true // default false
        maintainPositionOnInputBarHeightChanged = true // default false
        showMessageTimestampOnSwipeLeft = false // default false
        //        messagesCollectionView.refreshControl = refreshControl
        messagesCollectionView.reloadData()
    }
    
    func configureMessageInputBar() {
        let clearView = UIView()
        clearView.backgroundColor = .clear

        if viewModel.uiStyle == .chat {
            clearView.addSubview(inputBarVC.view)
            inputBarVC.view.snp.makeConstraints { make in
                make.leading.equalTo(0)
                make.trailing.equalTo(0)
                make.top.equalTo(0)
                make.bottom.equalTo(0)
            }
        }
        inputBarType = .custom(clearView)
        
        
        let redView = UIView()
        redView.backgroundColor = .red
        view.addSubview(redView)
        redView.snp.makeConstraints { make in
            make.leading.equalTo(20)
            make.trailing.equalTo(-20)
            make.height.equalTo(30)
//            make.bottom.equalTo(-10)
            make.bottom.equalTo(inputContainerView.snp.top).offset(-10)
            
        }
        
        
        
    }
    
    // MARK: - Helpers
    var lastIndexPath:IndexPath{
        if messageList.count == 0 {
            return IndexPath(item: 0, section: 0)
        }
        return IndexPath(item: messageList.count - 1, section: 0)
    }
    
    func insertMessage(_ message: TSChatMessage) {
        messageList.append(message)
        messagesCollectionView.performBatchUpdates({
            messagesCollectionView.insertItems(at: [lastIndexPath])
            if messageList.count >= 2 {
                messagesCollectionView.reloadItems(at: [lastIndexPath])
            }
        }, completion: { [weak self] _ in
            if self?.isLastSectionVisible() == true {
                self?.messagesCollectionView.scrollToLastItem(animated: true)
            }
        })
    }
    
    func isLastSectionVisible() -> Bool {
        guard !messageList.isEmpty else { return false }
        return messagesCollectionView.indexPathsForVisibleItems.contains(lastIndexPath)
    }
    
    private let formatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        return formatter
    }()
}


// MARK: MessagesDataSource
extension TSChatViewController {
    
    var currentSender: SenderType {
        return viewModel.kUserSender
    }
    
    func numberOfSections(in _: MessagesCollectionView) -> Int {
        return 1
    }
    
    func numberOfItems(inSection section: Int, in messagesCollectionView: MessagesCollectionView) -> Int{
        messageList.count
    }
    
    func messageForItem(at indexPath: IndexPath, in _: MessagesCollectionView) -> MessageType {
        messageList[indexPath.item]
    }
    
    func cellTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
//        if indexPath.item % 3 == 0 {
//            return NSAttributedString(
//                string: MessageKitDateFormatter.shared.string(from: message.sentDate),
//                attributes: [
//                    NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 10),
//                    NSAttributedString.Key.foregroundColor: UIColor.darkGray,
//                ])
//        }
        return nil
    }
    
    func cellBottomLabelAttributedText(for _: MessageType, at _: IndexPath) -> NSAttributedString? {
        NSAttributedString(
            string: "Read",
            attributes: [
                NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 10),
                NSAttributedString.Key.foregroundColor: UIColor.darkGray,
            ])
    }
    
    func messageTopLabelAttributedText(for message: MessageType, at _: IndexPath) -> NSAttributedString? {
        let name = message.sender.displayName
        return NSAttributedString(
            string: name,
            attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption1)])
    }
    
    func messageBottomLabelAttributedText(for message: MessageType, at _: IndexPath) -> NSAttributedString? {
        let dateString = formatter.string(from: message.sentDate)
        return NSAttributedString(
            string: dateString,
            attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption2)])
    }
    
    func textCell(
        for message: MessageType,
        at indexPath: IndexPath,
        in messagesCollectionView: MessagesCollectionView)
    -> UICollectionViewCell?
    {
        let cell = messagesCollectionView.dequeueReusableCell(
            TSTextMessageContentCell.self,
            for: indexPath)
        cell.configure(
            with: message,
            at: indexPath,
            in: messagesCollectionView,
            dataSource: self,
            and: textMessageSizeCalculator)
        
        return cell
    }
}


// MARK: InputBarAccessoryViewDelegate

extension TSChatViewController: InputBarAccessoryViewDelegate {
    // MARK: Internal
    
    @objc
    func inputBar(_: InputBarAccessoryView, didPressSendButtonWith _: String) {
        processInputBar(messageInputBar)
    }
    
    //聊天发送内容
    func processInputBar(_ inputBar: InputBarAccessoryView) {
        // Here we can parse for which substrings were autocompleted
        let attributedText = inputBar.inputTextView.attributedText!
        let range = NSRange(location: 0, length: attributedText.length)
        attributedText.enumerateAttribute(.autocompleted, in: range, options: []) { _, range, _ in
            
            let substring = attributedText.attributedSubstring(from: range)
            let context = substring.attribute(.autocompletedContext, at: 0, effectiveRange: nil)
            print("Autocompleted: `", substring, "` with context: ", context ?? "-")
        }
        
        let components = inputBar.inputTextView.components
        inputBar.inputTextView.text = String()
        inputBar.invalidatePlugins()
        
        inputBar.inputTextView.placeholder = "Aa"
        sendMessages(components)
        messagesCollectionView.scrollToLastItem(animated: true)
    }
    
    // MARK: Private
    
    private func sendMessages(_ data: [Any]) {
        let user = viewModel.kUserSender
        for component in data {
            if let str = component as? String {
                let message = TSChatMessage(text: str, user: user, messageId: UUID().uuidString, date: Date())
                insertMessage(message)
                //保存这条消息到本地数据库
                //发送消息后,进行AI 对话生成
                generativeAIChat(message: message)
            } else if let img = component as? UIImage {
                //              let message = TSChatMessage(image: img, user: user, messageId: UUID().uuidString, date: Date())
                //              insertMessage(message)
            }
        }
    }
    
    func generativeAIChat(message:TSChatMessage) {
        var messageString = ""
        switch message.kind {
        case .text(let message):
            messageString = message
        default:
            break
        }
        
        if messageString.count == 0 {
            return
        }
        
        let message = TSChatMessage(attributedText: kMDAttributedString(text: ""), user: viewModel.kAIUser, messageId: UUID().uuidString, date: Date())
        message.sendState = .start
        insertMessage(message)
        
        inputBarVC.sendEnabled(enabled: false)
        viewModel.sendChatMessage(message: messageString) {[weak self] string in
            guard let self = self else { return }
            debugPrint("viewModel.AiMDString=\(viewModel.AiMDString)")
            message.kind = .attributedText(kMDAttributedString(text: viewModel.AiMDString))
            message.sendState = .progress(0.5)
            updataAIChatCellUI()
            
        } completion: {[weak self] data, error in
            guard let self = self else { return }
            if let netData = data {
                message.sendState = .success("netData")
                //保存这条消息到本地数据库
            }else {
                message.kind = .attributedText(kMDAttributedString(text: kAIErrorString))
                message.sendState = .failed(kAIErrorString)
                //保存这条消息到本地数据库
            }
            updataAIChatCellUI()
            
            kExecuteOnMainThread {
                self.inputBarVC.sendEnabled(enabled: true)
            }
        }
    }
    
    func updataAIChatCellUI(){
        kExecuteOnMainThread {
            if self.messageList.count >= 2 {
                UIView.performWithoutAnimation {
                    self.messagesCollectionView.reloadItems(at: [self.lastIndexPath])
                }
            }else{
                self.messagesCollectionView.reloadData()
            }
            
//            if self.isLastSectionVisible() == true {
                self.messagesCollectionView.scrollToLastItem(animated: false)
//            }
        }
    }
    
}

