<commit_before>//
//  PXSecurityCodeViewController.swift
//  MercadoPagoSDK
//
//  Created by <NAME> on 04/08/2020.
//

import Foundation
import MLUI
import MLCardDrawer
import AndesUI

final class PXSecurityCodeViewController: MercadoPagoUIViewController {

    let viewModel: PXSecurityCodeViewModel
    let cardContainerView = UIView()
    let titleLabel = UILabel()
    let subtitleLabel = UILabel()
    var loadingButtonComponent: PXAnimatedButton?
    var cardDrawer: MLCardDrawerController?
    var attemptsWithInternetError: Int = 0
    var andesTextFieldCode = AndesTextFieldCode()
    var andesTextFieldCodeIsComplete = false

    // MARK: Constraints
    var loadingButtonBottomConstraint = NSLayoutConstraint()
    var titleLabelTopConstraint = NSLayoutConstraint()
    var subtitleTopConstraint = NSLayoutConstraint()
    var textFieldContainerTopConstraint = NSLayoutConstraint()
    var textFieldContainerBottomConstraint = NSLayoutConstraint()
    var andesTextFieldCodeCenterYConstraint = NSLayoutConstraint()

    // MARK: Callbacks
    let finishButtonAnimationCallback: () -> Void
    let collectSecurityCodeCallback: (PXCardInformationForm, String?) -> Void

    init(viewModel: PXSecurityCodeViewModel, finishButtonAnimationCallback: @escaping () -> Void, collectSecurityCodeCallback: @escaping (PXCardInformationForm, String?) -> Void) {
        self.viewModel = viewModel
        self.finishButtonAnimationCallback = finishButtonAnimationCallback
        self.collectSecurityCodeCallback = collectSecurityCodeCallback
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        trackScreenView()
        setNavBarBackgroundColor(color: .white)
        setNavBarTextColor(color: .black)
        renderViews()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        setupKeyboardNotifications()
        setupNavBarStyle(style: .default)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setupAnimations()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        removeKeyboardNotifications()
        loadingButtonComponent?.dismissSnackbar()
        setupNavBarStyle(style: ThemeManager.shared.navigationControllerMemento?.navBarStyle ?? .black)
    }
}

// MARK: Privates
private extension PXSecurityCodeViewController {
    func confirmPayment() {
        trackEvent(path: TrackingPaths.Events.SecurityCode.getConfirmPath(), properties: viewModel.getScreenProperties())
        doPayment()
    }

    func doPayment() {
        if viewModel.internetProtocol?.hasInternetConnection() ?? true {
            enableUI(false)
            andesTextFieldCode.setFocus()
            subscribeLoadingButtonToNotifications()
            loadingButtonComponent?.startLoading(timeOut: 15)
            collectSecurityCodeCallback(viewModel.cardInfo, andesTextFieldCode.text)
        } else {
            trackEvent(path: TrackingPaths.Events.getErrorPath(), properties: viewModel.getNoConnectionProperties())
            attemptsWithInternetError += 1
            if attemptsWithInternetError < 4 {
                loadingButtonComponent?.showErrorToast(title: "px_connectivity_neutral_error".localized, actionTitle: nil, type: MLSnackbarType.default(), duration: MLSnackbarDuration.short, action: nil)
            } else {
                progressButtonAnimationTimeOut()
            }
        }
    }

    func subscribeLoadingButtonToNotifications() {
        guard let loadingButton = loadingButtonComponent else { return }
        PXNotificationManager.SuscribeTo.animateButton(loadingButton, selector: #selector(loadingButton.animateFinish))
    }

    func enableUI(_ enabled: Bool) {
        view.isUserInteractionEnabled = enabled
        navigationController?.navigationBar.isUserInteractionEnabled = enabled
        if enabled, andesTextFieldCodeIsComplete {
            loadingButtonComponent?.isUserInteractionEnabled = true
        } else {
            loadingButtonComponent?.isUserInteractionEnabled = false
        }
    }

    func unsubscribeFromNotifications() {
        PXNotificationManager.UnsuscribeTo.animateButton(loadingButtonComponent)
    }
}

// MARK: PXAnimatedButtonDelegate
extension PXSecurityCodeViewController: PXAnimatedButtonDelegate {
    func shakeDidFinish() {
        displayBackButton()
        enableUI(true)
        unsubscribeFromNotifications()
        UIView.animate(withDuration: 0.3, animations: {
            self.loadingButtonComponent?.backgroundColor = self.andesTextFieldCodeIsComplete ? ThemeManager.shared.getAccentColor() : ThemeManager.shared.greyColor()
        })
    }

    func expandAnimationInProgress() {
        andesTextFieldCode.removeFocus()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
            self?.hideNavBar()
        }
    }

    func didFinishAnimation() {<commit_msg>Disable CVV fields while making payment<commit_after>//
//  PXSecurityCodeViewController.swift
//  MercadoPagoSDK
//
//  Created by <NAME> on 04/08/2020.
//

import Foundation
import MLUI
import MLCardDrawer
import AndesUI

final class PXSecurityCodeViewController: MercadoPagoUIViewController {

    let viewModel: PXSecurityCodeViewModel
    let cardContainerView = UIView()
    let titleLabel = UILabel()
    let subtitleLabel = UILabel()
    var loadingButtonComponent: PXAnimatedButton?
    var cardDrawer: MLCardDrawerController?
    var attemptsWithInternetError: Int = 0
    var andesTextFieldCode = AndesTextFieldCode()
    var andesTextFieldCodeIsComplete = false

    // MARK: Constraints
    var loadingButtonBottomConstraint = NSLayoutConstraint()
    var titleLabelTopConstraint = NSLayoutConstraint()
    var subtitleTopConstraint = NSLayoutConstraint()
    var textFieldContainerTopConstraint = NSLayoutConstraint()
    var textFieldContainerBottomConstraint = NSLayoutConstraint()
    var andesTextFieldCodeCenterYConstraint = NSLayoutConstraint()

    // MARK: Callbacks
    let finishButtonAnimationCallback: () -> Void
    let collectSecurityCodeCallback: (PXCardInformationForm, String?) -> Void

    init(viewModel: PXSecurityCodeViewModel, finishButtonAnimationCallback: @escaping () -> Void, collectSecurityCodeCallback: @escaping (PXCardInformationForm, String?) -> Void) {
        self.viewModel = viewModel
        self.finishButtonAnimationCallback = finishButtonAnimationCallback
        self.collectSecurityCodeCallback = collectSecurityCodeCallback
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        trackScreenView()
        setNavBarBackgroundColor(color: .white)
        setNavBarTextColor(color: .black)
        renderViews()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        setupKeyboardNotifications()
        setupNavBarStyle(style: .default)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setupAnimations()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        removeKeyboardNotifications()
        loadingButtonComponent?.dismissSnackbar()
        setupNavBarStyle(style: ThemeManager.shared.navigationControllerMemento?.navBarStyle ?? .black)
    }
}

// MARK: Privates
private extension PXSecurityCodeViewController {
    func confirmPayment() {
        trackEvent(path: TrackingPaths.Events.SecurityCode.getConfirmPath(), properties: viewModel.getScreenProperties())
        doPayment()
    }

    func doPayment() {
        if viewModel.internetProtocol?.hasInternetConnection() ?? true {
            enableUI(false)
            andesTextFieldCode.setFocus()
            subscribeLoadingButtonToNotifications()
            loadingButtonComponent?.startLoading(timeOut: 15)
            collectSecurityCodeCallback(viewModel.cardInfo, andesTextFieldCode.text)
        } else {
            trackEvent(path: TrackingPaths.Events.getErrorPath(), properties: viewModel.getNoConnectionProperties())
            attemptsWithInternetError += 1
            if attemptsWithInternetError < 4 {
                loadingButtonComponent?.showErrorToast(title: "px_connectivity_neutral_error".localized, actionTitle: nil, type: MLSnackbarType.default(), duration: MLSnackbarDuration.short, action: nil)
            } else {
                progressButtonAnimationTimeOut()
            }
        }
    }

    func subscribeLoadingButtonToNotifications() {
        guard let loadingButton = loadingButtonComponent else { return }
        PXNotificationManager.SuscribeTo.animateButton(loadingButton, selector: #selector(loadingButton.animateFinish))
    }

    func enableUI(_ enabled: Bool) {
        view.isUserInteractionEnabled = enabled
        navigationController?.navigationBar.isUserInteractionEnabled = enabled
        if enabled, andesTextFieldCodeIsComplete {
            andesTextFieldCode.state = .IDLE
            loadingButtonComponent?.isUserInteractionEnabled = true
        } else {
            andesTextFieldCode.state = .DISABLED
            loadingButtonComponent?.isUserInteractionEnabled = false
        }
    }

    func unsubscribeFromNotifications() {
        PXNotificationManager.UnsuscribeTo.animateButton(loadingButtonComponent)
    }
}

// MARK: PXAnimatedButtonDelegate
extension PXSecurityCodeViewController: PXAnimatedButtonDelegate {
    func shakeDidFinish() {
        displayBackButton()
        enableUI(true)
        unsubscribeFromNotifications()
        UIView.animate(withDuration: 0.3, animations: {
            self.loadingButtonComponent?.backgroundColor = self.andesTextFieldCodeIsComplete ? ThemeManager.shared.getAccentColor() : ThemeManager.shared.greyColor()
        })
    }

    func expandAnimationInProgress() {
        andesTextFieldCode.removeFocus()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
            self?.hideNavBar()
        }
    }

    func didFinishAnimation() {
{'fraction_non_alphanumeric': 0.07854110382091857, 'fraction_numerical': 0.0032805866460825935, 'mean_word_length': 3.4219283276450514, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5328662', 'n_tokens_mistral': 2757, 'n_tokens_neox': 2609, 'n_words': 505}