//
//  HexEditUITextView.swift
//  ABC Bluetooth Demo
//
//  Created by AB Circle on 19/11/2020.
//  Copyright © 2020-2024 AB Circle. All rights reserved.
//

import Foundation
import Foundation
import UIKit

/// Class overriding an UITextView in order to enable hexadecimal input only.
/// It uses a delegate function to check entered text and allows 0~9, space and A~F characters only.
/// Also disabled the autocompletion feature that turns 2 spaces into a dot plus space.
class HexEditUITextView: UITextView {
    
    /// Override initialiser.
    ///
    /// - Parameters:
    ///   - frame: CGRect
    ///   - textContainer: NSTextContainer
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        
        initialise()
    }
    
    /// Required initialiser.
    /// - Parameter coder: NSCoder
    required init?(coder: NSCoder) {
        super.init(coder: coder)

        initialise()
    }
    
    /// Sets the delegate and initialises the text view borders
    private func initialise() {
        self.delegate = self
        self.autocapitalizationType = .allCharacters
        self.layer.borderWidth  = 1.0
        self.layer.cornerRadius = 8
        self.layer.borderColor  =  UIColor.lightGray.cgColor
    }
}

extension HexEditUITextView: UITextViewDelegate {
    /// Tells the delegate when the user changes the text or attributes in the specified text view.
    /// Used here to fix the ". " back to double space
    ///
    /// - Parameter textView: The text view containing the changes.
    func textViewDidChange(_ textView: UITextView)
    {
        text = text.replacingOccurrences(of: ". ", with: "  ")
    }
    
    /// Asks the delegate whether to replace the specified text in the text view.
    /// Used here to check if entered text conforms a characterset holding hexadecimal values + space.
    ///
    /// - Parameters:
    ///   - textView: The text view containing the changes.
    ///   - range: The current selection range.
    ///   - text: The text to insert
    /// - Returns: True if the old text should be replaced by the new text; false if the replacement operation should be aborted.
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        var result: Bool = false
        
        if text.isEmpty {
            result = true
        }
        else {
            let allowed = CharacterSet(charactersIn:"0123456789 ABCDEF")

            result = (text.rangeOfCharacter(from: allowed) != nil)
            if (result && textView.text.contains(".")) {
                let newText   = textView.text.replacingOccurrences(of: ".", with: " ")
                textView.text = newText
                result = false
            }
        }
        return result
    }
}
