import Foundation
import UIKit
import AsyncDisplayKit
import Display
import TelegramCore
import TelegramStringFormatting
import PhoneNumberFormat

private func removeDuplicatedPlus(_ text: String?) -> String {
    var result = ""
    if let text = text {
        for c in text {
            if c == "+" {
                if result.isEmpty {
                    result += String(c)
                }
            } else {
                result += String(c)
            }
        }
    }
    return result
}

private func removePlus(_ text: String?) -> String {
    var result = ""
    if let text = text {
        for c in text {
            if c != "+" {
                result += String(c)
            }
        }
    }
    return result
}

private func cleanPhoneNumber(_ text: String?) -> String {
    var cleanNumber = ""
    if let text = text.flatMap({ normalizeArabicNumeralString($0, type: .western) }) {
        for c in text {
            if c == "+" {
                if cleanNumber.isEmpty {
                    cleanNumber += String(c)
                }
            } else if c >= "0" && c <= "9" {
                cleanNumber += String(c)
            }
        }
    }
    return cleanNumber
}

private func cleanPrefix(_ text: String) -> String {
    var result = ""
    var checked = false
    for c in text {
        if c != " " {
            checked = true
        }
        if checked {
            result += String(c)
        }
    }
    return result
}

private func cleanSuffix(_ text: String) -> String {
    var result = ""
    var checked = false
    for c in text.reversed() {
        if c != " " {
            checked = true
        }
        if checked {
            result = String(c) + result
        }
    }
    return result
}

public final class SinglePhoneInputNode: ASDisplayNode, UITextFieldDelegate {
    private let fontSize: CGFloat
    
    public var numberField: TextFieldNode?
    public var numberFieldText: String?
    
    public var enableEditing: Bool = true
    
    public var number: String {
        get {
            return cleanPhoneNumber(self.numberField?.textField.text ?? "")
        } set(value) {
            self.updateNumber(value)
        }
    }
    public var numberUpdated: ((String) -> Void)?
    public var beginEditing: (() -> Void)?
    public var endEditing: (() -> Void)?
    
    private let phoneFormatter = InteractivePhoneFormatter()
    
    private var validLayout: CGSize?
    
    public init(fontSize: CGFloat = 20.0) {
        self.fontSize = fontSize
        
        super.init()
    }
    
    override public func didLoad() {
        super.didLoad()
        
        let numberField = TextFieldNode()
        numberField.textField.font = Font.regular(self.fontSize)
        numberField.textField.keyboardType = .phonePad
        numberField.textField.text = self.numberFieldText
        
        self.addSubnode(numberField)
        
        numberField.textField.addTarget(self, action: #selector(self.numberTextChanged(_:)), for: .editingChanged)
        numberField.textField.delegate = self
        
        self.numberField = numberField
        
        if let size = self.validLayout {
            numberField.frame = CGRect(origin: CGPoint(), size: size)
        }
    }
    
    @objc private func numberTextChanged(_ textField: UITextField) {
        self.updateNumberFromTextFields()
    }
    
    public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return self.enableEditing
    }
    
    public func textFieldDidBeginEditing(_ textField: UITextField) {
        self.beginEditing?()
    }
    
    public func textFieldDidEndEditing(_ textField: UITextField) {
        self.endEditing?()
    }
    
    private func updateNumberFromTextFields() {
        guard let numberField = self.numberField else {
            return
        }
        let inputText = removeDuplicatedPlus(cleanPhoneNumber(numberField.textField.text))
        self.updateNumber(inputText)
        self.numberUpdated?(inputText)
    }
    
    private func updateNumber(_ inputText: String) {
        let (_, numberText) = self.phoneFormatter.updateText(inputText)
        guard let numberField = self.numberField else {
            self.numberFieldText = numberText
            return
        }
        
        if numberText != numberField.textField.text {
            numberField.textField.text = numberText
        }
    }
    
    public func updateLayout(size: CGSize) {
        self.validLayout = size
        self.numberField?.frame = CGRect(origin: CGPoint(), size: size)
    }
}