// Copyright © 2022 Olo Inc. All rights reserved.
// This software is made available under the Olo Pay SDK License (See LICENSE.md file)
//
//  PaymentCardDetailsView.swift
//  OlopaysdkReactNative
//
//  Created by Justin Anderson on 3/2/23.
//  Copyright © 2023 Facebook. All rights reserved.
//

import Foundation

// This class is the view that is exposed to React Native. Internally everything gets
// redirected to PaymentCardDetailsViewController. When this view runs through the first layout
// pass the following things take place (in the embed() method):
// 1. A PaymentCardDetailsViewController instance is created and added as a child to this
//    view's parentViewController, which is controlled by React Native
// 2. The PaymentCardDetailsViewController's view is added as a subview to this
//    PaymentCardDetailsView instance
// 3. The view controller created in step 1 gets the same frame size as the bounds of this view
//
// This is all done pre-emptively to support view controllers. There is a future payment processor
// that may be added to the Olo Pay SDK that only works with view controllers. As a result, the Olo Pay
// iOS SDK may deprecate it's views and switch to using view controllers. If that happens, we may
// end up removing PaymentCardDetailsViewController and using the view controller exposed by the
// iOS SDK, but all the major plumbing to support view controllers in React Native will already
// be in place, leading to a smoother transition
@objc class PaymentCardDetailsView : OloPayView {
    private var paymentViewController: PaymentCardDetailsViewController? {
        get { return viewController as? PaymentCardDetailsViewController }
    }
    
    @objc override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    @objc required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // This method allows React Native to change the size of the native view
    // to keep the native view and it's React Native host view size in sync
    override func reactSetFrame(_ frame: CGRect) {
        super.reactSetFrame(frame)
        self.frame = frame
        
        guard let paymentViewController = paymentViewController else {
            return
        }
        
        paymentViewController.view.frame = frame
    }
    
    @objc public func focus() { paymentViewController?.focus() }
    @objc public func blur() { paymentViewController?.blur() }
    @objc public func clear() { paymentViewController?.clear() }
    
    @objc public func createPaymentMethod(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        paymentViewController?.createPaymentMethod(resolve: resolve, reject: reject)
    }
    
    @objc var onCardChangeEvent: RCTDirectEventBlock? = nil {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.onCardChange = onCardChangeEvent
        }
    }

    @objc var onFocusEvent: RCTDirectEventBlock? = nil {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.onFocus = onFocusEvent
        }
    }

    @objc var onFocusFieldEvent: RCTDirectEventBlock? = nil {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.onFocusField = onFocusFieldEvent
        }
    }

    @objc var onBlurEvent: RCTDirectEventBlock? = nil {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.onBlur = onBlurEvent
        }
    }

    @objc public var postalCodeEnabled: Bool = true {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.postalCodeEnabled = postalCodeEnabled
        }
    }

    @objc public var isEnabled: Bool = true {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.isEnabled = isEnabled
        }
    }

    @objc public var placeholders: NSDictionary = NSDictionary() {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.placeholders = placeholders
        }
    }

    @objc public var cardStyles: NSDictionary = NSDictionary() {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.cardStyles = cardStyles
        }
    }
    
    @objc public var customErrorMessages: NSDictionary = NSDictionary() {
        didSet {
            guard let paymentCardViewController = paymentViewController else {
                viewIsDirty = true
                return
            }

            paymentCardViewController.customErrorMessages = customErrorMessages
        }
    }

    override func updateAllProperties() {
        guard let paymentCardViewController = paymentViewController else {
            return
        }

        paymentCardViewController.postalCodeEnabled = postalCodeEnabled
        paymentCardViewController.isEnabled = isEnabled
        paymentCardViewController.placeholders = placeholders
        paymentCardViewController.cardStyles = cardStyles
        paymentCardViewController.onCardChange = onCardChangeEvent
        paymentCardViewController.onFocus = onFocusEvent
        paymentCardViewController.onFocusField = onFocusFieldEvent
        paymentCardViewController.onBlur = onBlurEvent
        paymentCardViewController.customErrorMessages = customErrorMessages
    }
    
    override func createViewController() -> UIViewController {
        return PaymentCardDetailsViewController()
    }
}
