//! Types related to the Stripe JS SDK.
//!
//! We plan to research ways to remove first-party support for Stripe while still making it easy
//! for third-party developers to write some sort of plugin/add-on/component/etc that can be used
//! to get the same functionality that we're currently providing.

use crate::context::crate_private::CratePrivate;
use crate::context::Context;
use crate::ComponentImports;

/// An initialized Stripe JS SDK instance.
///
/// ## Stripe Documentation
/// https://docs.stripe.com/js/initializing
#[repr(C)]
pub struct StripeJsSdkInstanceHandle(i64);
impl StripeJsSdkInstanceHandle {
    /// TODO: Delete this once the `pm-checkout-page` component is fully converted to using
    ///  `afia-component`.
    ///  Basically:
    ///  1. don't use this method for anything new
    ///  2. once this method is unused we can delete it
    pub fn temporary_way_to_get_i64(&self) -> i64 {
        self.0
    }
}

/// An initialized Stripe Elements instance.
///
/// ## Stripe Documentation
/// https://docs.stripe.com/js/elements_object
#[repr(C)]
pub struct StripeElementsHandle(i64);
impl StripeElementsHandle {
    /// TODO: Delete this once the `pm-checkout-page` component is fully converted to using
    ///  `afia-component`.
    ///  Basically:
    ///  1. don't use this method for anything new
    ///  2. once this method is unused we can delete it
    pub fn temporary_way_to_get_i64(&self) -> i64 {
        self.0
    }
}

impl ComponentImports {
    /// Initialize the Stripe JS SDK.
    pub fn initialize_stripe<C: Context>(&self, context: C) {
        let context = context.to_isize(CratePrivate);
        unsafe { afia_component_sys::initialize_stripe(self.component_imports_ptr, context) };
    }

    /// Create a Stripe Elements object.
    pub fn create_stripe_elements(
        &self,
        handle: &StripeJsSdkInstanceHandle,
        amount_cents: u32,
    ) -> StripeElementsHandle {
        let elements = unsafe {
            afia_component_sys::create_stripe_elements(
                self.component_imports_ptr,
                handle.0,
                amount_cents,
            )
        };

        StripeElementsHandle(elements)
    }

    /// Submit a Stripe Elements object.
    pub fn submit_stripe_elements<C: Context>(&self, handle: &StripeElementsHandle, context: C) {
        let context = context.to_isize(CratePrivate);
        unsafe {
            afia_component_sys::submit_stripe_elements(
                self.component_imports_ptr,
                handle.0,
                context,
            )
        };
    }
}
