import Foundation
import UIKit
import Display
import AsyncDisplayKit
import TelegramPresentationData

enum SetupTwoStepVerificationInputType {
    case password
    case text
    case code
    case email
}

struct SetupTwoStepVerificationContentAction {
    let title: String
    let action: () -> Void
}

final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDelegate {
    private var theme: PresentationTheme
    let kind: SetupTwoStepVerificationStateKind
    private let leftAction: SetupTwoStepVerificationContentAction?
    private let rightAction: SetupTwoStepVerificationContentAction?
    private let textUpdated: (String) -> Void
    private let returnPressed: () -> Void
    
    private let titleNode: ImmediateTextNode
    private let subtitleNode: ImmediateTextNode
    private let inputNode: TextFieldNode
    private let inputSeparator: ASDisplayNode
    private let leftActionButton: HighlightableButtonNode
    private let rightActionButton: HighlightableButtonNode
    
    private var isEnabled = true
    private var clearOnce: Bool = false
    
    init(theme: PresentationTheme, kind: SetupTwoStepVerificationStateKind, title: String, subtitle: String, inputType: SetupTwoStepVerificationInputType, placeholder: String, text: String, isPassword: Bool, textUpdated: @escaping (String) -> Void, returnPressed: @escaping () -> Void, leftAction: SetupTwoStepVerificationContentAction?, rightAction: SetupTwoStepVerificationContentAction?) {
        self.theme = theme
        self.kind = kind
        self.leftAction = leftAction
        self.rightAction = rightAction
        self.textUpdated = textUpdated
        self.returnPressed = returnPressed
        
        self.titleNode = ImmediateTextNode()
        self.titleNode.maximumNumberOfLines = 0
        self.titleNode.displaysAsynchronously = false
        self.titleNode.textAlignment = .center
        self.titleNode.attributedText = NSAttributedString(string: title, font: Font.light(30.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
        
        self.subtitleNode = ImmediateTextNode()
        self.subtitleNode.maximumNumberOfLines = 0
        self.subtitleNode.displaysAsynchronously = false
        self.subtitleNode.textAlignment = .center
        self.subtitleNode.attributedText = NSAttributedString(string: subtitle, font: Font.regular(16.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
        
        self.inputNode = TextFieldNode()
        self.inputNode.textField.textColor = theme.list.itemPrimaryTextColor
        self.inputNode.textField.font = Font.regular(22.0)
        self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(22.0), textColor: theme.list.itemPlaceholderTextColor)
        self.inputNode.textField.textAlignment = .center
        self.inputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
        self.inputNode.textField.tintColor = theme.list.itemAccentColor
        switch inputType {
            case .password:
                self.inputNode.textField.isSecureTextEntry = true
                self.inputNode.textField.autocapitalizationType = .none
                self.inputNode.textField.autocorrectionType = .no
                if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
                    #if DEBUG
                    self.inputNode.textField.textContentType = .newPassword
                    #endif
                }
            case .text:
                break
            case .code:
                self.inputNode.textField.autocapitalizationType = .none
                self.inputNode.textField.autocorrectionType = .no
                if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
                    self.inputNode.textField.keyboardType = .asciiCapableNumberPad
                } else {
                    self.inputNode.textField.keyboardType = .numberPad
                }
                if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
                    self.inputNode.textField.textContentType = .oneTimeCode
                }
            case .email:
                self.inputNode.textField.autocapitalizationType = .none
                self.inputNode.textField.autocorrectionType = .no
                self.inputNode.textField.keyboardType = .emailAddress
                if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
                    self.inputNode.textField.textContentType = .emailAddress
                }
        }
        self.inputSeparator = ASDisplayNode()
        self.inputSeparator.isLayerBacked = true
        self.inputSeparator.backgroundColor = theme.list.itemPlainSeparatorColor
        
        self.leftActionButton = HighlightableButtonNode()
        self.leftActionButton.hitTestSlop = UIEdgeInsets(top: -10.0, left: -16.0, bottom: -10.0, right: -16.0)
        self.rightActionButton = HighlightableButtonNode()
        self.rightActionButton.hitTestSlop = UIEdgeInsets(top: -10.0, left: -16.0, bottom: -10.0, right: -16.0)
        
        super.init()
        
        self.addSubnode(self.titleNode)
        self.addSubnode(self.subtitleNode)
        self.addSubnode(self.inputNode)
        self.addSubnode(self.inputSeparator)
        
        self.inputNode.textField.addTarget(self, action: #selector(self.inputNodeTextChanged(_:)), for: .editingChanged)
        self.inputNode.textField.returnKeyType = .next
        self.inputNode.textField.delegate = self
        
        if let leftAction = self.leftAction {
            self.leftActionButton.setAttributedTitle(NSAttributedString(string: leftAction.title, font: Font.regular(16.0), textColor: theme.list.itemAccentColor), for: [])
            self.leftActionButton.setAttributedTitle(NSAttributedString(string: leftAction.title, font: Font.regular(16.0), textColor: theme.list.itemDisabledTextColor), for: [.disabled])
            self.addSubnode(self.leftActionButton)
            self.leftActionButton.addTarget(self, action: #selector(self.actionButtonPressed(_:)), forControlEvents: .touchUpInside)
        }
        if let rightAction = self.rightAction {
            self.rightActionButton.setAttributedTitle(NSAttributedString(string: rightAction.title, font: Font.regular(16.0), textColor: theme.list.itemAccentColor), for: [])
            self.rightActionButton.setAttributedTitle(NSAttributedString(string: rightAction.title, font: Font.regular(16.0), textColor: theme.list.itemDisabledTextColor), for: [.disabled])
            self.addSubnode(self.rightActionButton)
            self.rightActionButton.addTarget(self, action: #selector(self.actionButtonPressed(_:)), forControlEvents: .touchUpInside)
        }
    }
    
    func updatePresentationData(_ presentationData: PresentationData) {
        self.theme = presentationData.theme
        self.inputNode.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
        self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor
        self.inputNode.textField.tintColor = self.theme.list.itemAccentColor
    }
    
    func updateIsEnabled(_ isEnabled: Bool) {
        self.isEnabled = isEnabled
        self.leftActionButton.isEnabled = isEnabled
        self.rightActionButton.isEnabled = isEnabled
    }
    
    func updateLayout(size: CGSize, insets: UIEdgeInsets, visibleInsets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
        let sidePadding: CGFloat = 20.0
        let sideButtonInset: CGFloat = 16.0
        let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - sidePadding * 2.0, height: .greatestFiniteMagnitude))
        let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: size.width - sidePadding * 2.0, height: .greatestFiniteMagnitude))
        
        let leftButtonSize = self.leftActionButton.measure(CGSize(width: size.width - sidePadding * 2.0, height: .greatestFiniteMagnitude))
        let rightButtonSize = self.rightActionButton.measure(CGSize(width: size.width - sidePadding * 2.0, height: .greatestFiniteMagnitude))
        let buttonsHeight: CGFloat
        if self.leftActionButton.supernode != nil || self.rightActionButton.supernode != nil {
            buttonsHeight = 56.0
        } else {
            buttonsHeight = 0.0
        }
        
        let titleSubtitleSpacing: CGFloat = 12.0
        
        let textHeight = titleSize.height + titleSubtitleSpacing + subtitleSize.height
        let inputHeight: CGFloat = 44.0
        let inputWidth: CGFloat = min(300.0, size.width - 37.0 * 2.0)
        
        let minContentHeight = textHeight + inputHeight
        let contentHeight = min(215.0, max(size.height - insets.top - insets.bottom - 40.0, minContentHeight))
        let contentOrigin = max(56.0, insets.top + floor((size.height - insets.top - insets.bottom - contentHeight) / 2.0))
        let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: contentOrigin), size: titleSize)
        transition.updateFrame(node: self.titleNode, frame: titleFrame)
        transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: floor((size.width - subtitleSize.width) / 2.0), y: titleFrame.maxY + titleSubtitleSpacing), size: subtitleSize))
        transition.updateFrame(node: self.inputSeparator, frame: CGRect(origin: CGPoint(x: floor((size.width - inputWidth) / 2.0), y: contentOrigin + contentHeight - UIScreenPixel), size: CGSize(width: inputWidth, height: UIScreenPixel)))
        transition.updateFrame(node: self.inputNode, frame: CGRect(origin: CGPoint(x: floor((size.width - inputWidth) / 2.0), y: contentOrigin + contentHeight - inputHeight), size: CGSize(width: inputWidth, height: inputHeight)))
        transition.updateFrame(node: self.leftActionButton, frame: CGRect(origin: CGPoint(x: sideButtonInset, y: size.height - visibleInsets.bottom - buttonsHeight + floor((buttonsHeight - leftButtonSize.height) / 2.0)), size: leftButtonSize))
        transition.updateFrame(node: self.rightActionButton, frame: CGRect(origin: CGPoint(x: size.width - sideButtonInset - rightButtonSize.width, y: size.height - visibleInsets.bottom - buttonsHeight + floor((buttonsHeight - rightButtonSize.height) / 2.0)), size: rightButtonSize))
    }
    
    func activate() {
        self.inputNode.textField.becomeFirstResponder()
    }
    
    func dataEntryError() {
        self.clearOnce = true
    }
    
    @objc private func inputNodeTextChanged(_ textField: UITextField) {
        self.textUpdated(textField.text ?? "")
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if self.clearOnce {
            self.clearOnce = false
            if range.length > string.count {
                textField.text = ""
                return false
            }
        }
        return true
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.returnPressed()
        return false
    }
    
    @objc private func actionButtonPressed(_ node: ASDisplayNode) {
        if node === self.leftActionButton {
            self.leftAction?.action()
        } else if node === self.rightActionButton {
            self.rightAction?.action()
        }
    }
}