//
//  EmojiTextField.swift
//  ComposeUI
//
//  Created by Shadowfacts on 3/5/23.
//

import SwiftUI

struct EmojiTextField: UIViewRepresentable {
    typealias UIViewType = UITextField
    
    @EnvironmentObject private var controller: ComposeController
    @Environment(\.colorScheme) private var colorScheme
    
    @Binding var text: String
    let placeholder: String
    let maxLength: Int?
    let becomeFirstResponder: Binding<Bool>?
    let focusNextView: Binding<Bool>?
    
    init(text: Binding<String>, placeholder: String, maxLength: Int?, becomeFirstResponder: Binding<Bool>? = nil, focusNextView: Binding<Bool>? = nil) {
        self._text = text
        self.placeholder = placeholder
        self.maxLength = maxLength
        self.becomeFirstResponder = becomeFirstResponder
        self.focusNextView = focusNextView
    }
    
    func makeUIView(context: Context) -> UITextField {
        let view = UITextField()
        view.borderStyle = .roundedRect
        view.font = .preferredFont(forTextStyle: .body)
        view.adjustsFontForContentSizeCategory = true
        view.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [
            .foregroundColor: UIColor.secondaryLabel,
        ])
        
        context.coordinator.textField = view
        
        view.delegate = context.coordinator
        view.addTarget(context.coordinator, action: #selector(Coordinator.didChange(_:)), for: .editingChanged)
        view.addTarget(context.coordinator, action: #selector(Coordinator.returnKeyPressed), for: .primaryActionTriggered)
        
        // otherwise when the text gets too wide it starts expanding the ComposeView
        view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        
        return view
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        if text != uiView.text {
            uiView.text = text
        }
        
        context.coordinator.text = $text
        context.coordinator.maxLength = maxLength
        context.coordinator.focusNextView = focusNextView
        
        uiView.backgroundColor = colorScheme == .dark ? UIColor(controller.config.fillColor) : .secondarySystemBackground
        
        if becomeFirstResponder?.wrappedValue == true {
            DispatchQueue.main.async {
                uiView.becomeFirstResponder()
                becomeFirstResponder!.wrappedValue = false
            }
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(controller: controller, text: $text, focusNextView: focusNextView)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate, ComposeInput {
        let controller: ComposeController
        var text: Binding<String>
        var focusNextView: Binding<Bool>?
        var maxLength: Int?
        
        @Published var autocompleteState: AutocompleteState?
        var autocompleteStatePublisher: Published<AutocompleteState?>.Publisher { $autocompleteState }
        
        weak var textField: UITextField?
        
        init(controller: ComposeController, text: Binding<String>, focusNextView: Binding<Bool>?, maxLength: Int? = nil) {
            self.controller = controller
            self.text = text
            self.focusNextView = focusNextView
            self.maxLength = maxLength
        }
        
        @objc func didChange(_ textField: UITextField) {
            text.wrappedValue = textField.text ?? ""
        }
        
        @objc func returnKeyPressed() {
            focusNextView?.wrappedValue = true
        }
        
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            if let maxLength {
                return ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string).count <= maxLength
            } else {
                return true
            }
        }
        
        func textFieldDidBeginEditing(_ textField: UITextField) {
            controller.currentInput = self
            autocompleteState = textField.updateAutocompleteState(permittedModes: .emojis)
        }
        
        func textFieldDidEndEditing(_ textField: UITextField) {
            controller.currentInput = nil
            autocompleteState = textField.updateAutocompleteState(permittedModes: .emojis)
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            autocompleteState = textField.updateAutocompleteState(permittedModes: .emojis)
        }
        
        // MARK: ComposeInput
        
        var toolbarElements: [ToolbarElement] { [.emojiPicker] }
        
        var textInputMode: UITextInputMode? {
            textField?.textInputMode
        }
        
        func applyFormat(_ format: StatusFormat) {
        }
        
        func beginAutocompletingEmoji() {
            textField?.insertText(":")
        }
        
        func autocomplete(with string: String) {
            textField?.autocomplete(with: string, permittedModes: .emojis, autocompleteState: &autocompleteState)
        }
    }
}
