//
//  Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//

import Foundation
import UIKit

@objc public class TextFieldHelper: NSObject {

    // Used to implement the UITextFieldDelegate method: `textField:shouldChangeCharactersInRange:replacementString`
    // Takes advantage of Swift's superior unicode handling to append partial pasted text without splitting multi-byte characters.
    @objc public class func textField(_ textField: UITextField, shouldChangeCharactersInRange editingRange: NSRange, replacementString: String, byteLimit: UInt) -> Bool {

        let byteLength = { (string: String) -> UInt in
            return UInt(string.utf8.count)
        }

        let existingString = textField.text ?? ""

        // Given an NSRange, we need to interact with the NS flavor of substring
        let removedString = (existingString as NSString).substring(with: editingRange)

        let lengthOfRemainingExistingString = byteLength(existingString) - byteLength(removedString)

        let newLength = lengthOfRemainingExistingString + byteLength(replacementString)

        if (newLength <= byteLimit) {
            return true
        }

        // Don't allow any change if inserting a single char is already over the limit (typically this means typing)
        if (replacementString.count < 2) {
            return false
        }

        // However if pasting, accept as much of the string as possible.
        let availableSpace = byteLimit - lengthOfRemainingExistingString

        var acceptableSubstring = ""

        for (_, char) in replacementString.enumerated() {
            var maybeAcceptableSubstring = acceptableSubstring
            maybeAcceptableSubstring.append(char)
            if (byteLength(maybeAcceptableSubstring) <= availableSpace) {
                acceptableSubstring = maybeAcceptableSubstring
            } else {
                break
            }
        }

        textField.text = (existingString as NSString).replacingCharacters(in: editingRange, with: acceptableSubstring)

        // We've already handled any valid editing manually, so prevent further changes.
        return false
    }
}