//
//  MdnEntryField.swift
//  MVMCoreUI
//
//  Created by Kevin Christiano on 10/21/19.
//  Copyright © 2019 Verizon Wireless. All rights reserved.
//

import AddressBookUI
import ContactsUI
import UIKit
import MVMCore

/**
 This class provides the convenience of formatting the MDN entered/displayer for the user.
 */
@objcMembers open class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate {
    //--------------------------------------------------
    // MARK: - Stored Properties
    //--------------------------------------------------
    
    public var isNationalMDN = true
    public var shouldValidateMDN = false
    
    //--------------------------------------------------
    // MARK: - Delegate
    //--------------------------------------------------
    
    /// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well.
    private weak var proprietorTextDelegate: UITextFieldDelegate?
    
    /// If you're using a MFViewController, you must set this to it
    public override weak var uiTextFieldDelegate: UITextFieldDelegate? {
        get { textField.delegate }
        set {
            textField.delegate = self
            proprietorTextDelegate = newValue
        }
    }
    
    //--------------------------------------------------
    // MARK: - Computed Properties
    //--------------------------------------------------
    
    /// Formats the MDN when setting and removes format of MDN when reading.
    public var mdn: String? {
        get { MVMCoreUIUtility.removeMdnFormat(text) }
        set { text = MVMCoreUIUtility.formatMdn(newValue) }
    }
    
    /// Toggles selected or original (unselected) UI.
    public override var isSelected: Bool {
        get { return entryFieldContainer.isSelected }
        set (selected) {
            if selected && showError {
                showError = false
            }
            
            super.isSelected = selected
        }
    }
    
    //--------------------------------------------------
    // MARK: - Initializers
    //--------------------------------------------------
    
    @objc public override init(frame: CGRect) {
        super.init(frame: .zero)
    }
    
    @objc public convenience init() {
        self.init(frame: .zero)
    }
    
    @objc required public init?(coder: NSCoder) {
        super.init(coder: coder)
        fatalError("MdnEntryField xib not supported.")
    }
    
    required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
        super.init(model: model, delegateObject, additionalData)
    }
    
    //--------------------------------------------------
    // MARK: - Setup
    //--------------------------------------------------
    
    @objc public override func setupFieldContainerContent(_ container: UIView) {
        super.setupFieldContainerContent(container)
        
        textField.keyboardType = .numberPad
    }
    
    open override func setupTextFieldToolbar() {
        
        let toolbar = UIToolbar.createEmptyToolbar()
        let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts))
        let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput))
        toolbar.items = [contacts, space, dismissButton]
        textField.inputAccessoryView = toolbar
    }
    
    //--------------------------------------------------
    // MARK: - Methods
    //--------------------------------------------------
    
    @objc public func hasValidMDN() -> Bool {
        
        guard let MDN = mdn, !MDN.isEmpty else { return false }
        
        if isNationalMDN {
            return MVMCoreUIUtility.validateMDNString(MDN)
        }
        
        return MVMCoreUIUtility.validateInternationalMDNString(MDN)
    }
    
    @objc public func validateMDNTextField() -> Bool {
        
        guard !shouldValidateMDN, let MDN = mdn, !MDN.isEmpty else {
            isValid = true
            return true
        }
        
        isValid = hasValidMDN()
        
        if self.isValid {
            showError = false
            
        } else {
            entryFieldModel?.errorMessage = entryFieldModel?.errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
            showError = true
            UIAccessibility.post(notification: .layoutChanged, argument: textField)
        }
        
        return isValid
    }
    
    @objc public func getContacts(_ sender: Any?) {
        
        let picker = CNContactPickerViewController()
        picker.delegate = self
        picker.displayedPropertyKeys = ["phoneNumbers"]
        picker.predicateForEnablingContact = NSPredicate(format: "phoneNumbers.@count > 0")
        picker.predicateForSelectionOfProperty = NSPredicate(format: "key == 'phoneNumbers'")
        MVMCoreNavigationHandler.shared()?.present(picker, animated: true)
    }
    
    //--------------------------------------------------
    // MARK: - MoleculeViewProtocol
    //--------------------------------------------------
    
    public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
        super.set(with: model, delegateObject, additionalData)
        
        textField.keyboardType = .phonePad
    }
    
    //--------------------------------------------------
    // MARK: - Contact Picker Delegate
    //--------------------------------------------------
    
    @objc public func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {
        
        if let phoneNumber = contactProperty.value as? CNPhoneNumber {
            
            let MDN = phoneNumber.stringValue
            var unformattedMDN = MVMCoreUIUtility.removeMdnFormat(MDN)
            
            // Sometimes user add extra 1 in front of mdn in their address book
            if isNationalMDN,
               let unformedMDN = unformattedMDN,
               unformedMDN.count == 11,
               unformedMDN[(unformedMDN.index(unformedMDN.startIndex, offsetBy: 0))] == "1" {
                
                let startIndex = unformedMDN.index(unformedMDN.startIndex, offsetBy: 1)
                unformattedMDN = String(unformedMDN[startIndex...])
            }
            
            text = unformattedMDN
            textFieldShouldReturn(textField)
            textFieldDidEndEditing(textField)
        }
    }
    
    //--------------------------------------------------
    // MARK: - Implemented TextField Delegate
    //--------------------------------------------------
    
    @discardableResult
    @objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        
        textField.resignFirstResponder()
        
        return proprietorTextDelegate?.textFieldShouldReturn?(textField) ?? true
    }
    
    @objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        
        if !MVMCoreUIUtility.validate(string, withRegularExpression: RegularExpressionDigitOnly) {
            return false
        }
        
        return proprietorTextDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true
    }
    
    @objc public func textFieldDidBeginEditing(_ textField: UITextField) {
        
        textField.text = MVMCoreUIUtility.removeMdnFormat(textField.text)
        proprietorTextDelegate?.textFieldDidBeginEditing?(textField)
    }
    
    @objc public func textFieldDidEndEditing(_ textField: UITextField) {
        
        proprietorTextDelegate?.textFieldDidEndEditing?(textField)
        
        if validateMDNTextField() && isNationalMDN {
            textField.text = MVMCoreUIUtility.formatMdn(textField.text)
        }
    }
    
    @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
    }
    
    @objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
        proprietorTextDelegate?.textFieldShouldEndEditing?(textField) ?? true
    }
    
    @objc public func textFieldShouldClear(_ textField: UITextField) -> Bool {
        proprietorTextDelegate?.textFieldShouldClear?(textField) ?? true
    }
}
