import {
  NativeModulesStatic,
  NativeModules,
} from 'react-native';
import {
  BlazeGAMCustomNativeAdsDelegate,
  BlazeCustomNativeAdsDelegateHelper
} from './BlazeGAMCustomNativeAdsDelegate';
import {
  BlazeBannerAdsDelegateHelper,
  BlazeGAMBannerAdsDelegate
} from './BlazeGAMBannerAdsDelegate';

interface BlazeGAMDefaultAdConfig {
  /**
   * Ad Unit in the GAM system.
   */
  adUnit: string;

  /**
   * Template ID in the GAM system.
   */
  templateId: string;
}

interface BlazeGAMEnableCustomNativeAdsOptions {

  /**
   * Default ad config to use if non is set in our system.
   */
  defaultAdConfig?: BlazeGAMDefaultAdConfig;

  /**
   * This delegate will be invoked upon different events.
   */
  delegate?: BlazeGAMCustomNativeAdsDelegate | null

}

/**
 * This Model is being sent to the native side.
 */
interface BlazeGAMEnableCustomNativeAdsOptionsNative {

  /**
   * Default ad config to use if non is set in our system.
   */
  defaultAdConfig?: BlazeGAMDefaultAdConfig;

}

interface BlazeGAMEnableBannerAdsOptions {

  /**
   * This delegate will be invoked upon different events.
   */
  delegate?: BlazeGAMBannerAdsDelegate | null

}

interface BlazeGAMInterface {

  /**
   * Call this function to enable Google Ads Manager Custom Native ads.
   * 
   * @param options
   * @param delegate 
   */
  enableCustomNativeAds(
    options: BlazeGAMEnableCustomNativeAdsOptions
  ): void;

  /**
   * Call this function to disable Google Ads Manager Custom Native ads.
   */
  disableCustomNativeAds(): void;

  /**
   * Call this function to enable Google Ads Manager Banner ads.
   * 
   * @param delegate 
   */
  enableBannerAds(
    options: BlazeGAMEnableBannerAdsOptions
  ): void

  /**
   * Call this function to disable Google Ads Manager Banner ads.
   */
  disableBannerAds(): void

}

interface BlazeGAMInterfaceInternal extends NativeModulesStatic {

  enableCustomNativeAds(
    options: BlazeGAMEnableCustomNativeAdsOptionsNative
  ): void;

  disableCustomNativeAds(): void;

  enableBannerAds(): void;

  disableBannerAds(): void;
}

const { RTNBlazeGAM } = NativeModules;
const BlazeGAMNativeModule = RTNBlazeGAM as BlazeGAMInterfaceInternal;

// This wrapper is hiding the internal interface that works with the native module, and serves as additional layer to add custom logic.
class BlazeGAMWrapper implements BlazeGAMInterface {

  enableCustomNativeAds(
    options: BlazeGAMEnableCustomNativeAdsOptions
  ): void {
    BlazeGAMNativeModule.enableCustomNativeAds({
      defaultAdConfig: options.defaultAdConfig
    });
    BlazeCustomNativeAdsDelegateHelper.registerDelegate(options.delegate)
  }

  disableCustomNativeAds(): void {
    BlazeGAMNativeModule.disableCustomNativeAds()
    BlazeCustomNativeAdsDelegateHelper.registerDelegate(null)
  }

  enableBannerAds(
    options: BlazeGAMEnableBannerAdsOptions
  ): void {
    BlazeGAMNativeModule.enableBannerAds();
    BlazeBannerAdsDelegateHelper.registerDelegate(options.delegate)
  }

  disableBannerAds(): void {
    BlazeGAMNativeModule.disableBannerAds()
    BlazeBannerAdsDelegateHelper.registerDelegate(null)
  }

  // Singleton instance
  private static instance: BlazeGAMWrapper;

  // Private constructor for singleton
  private constructor() { }

  // Method to get singleton instance
  public static getInstance(): BlazeGAMWrapper {
    if (!this.instance) {
      this.instance = new BlazeGAMWrapper();
    }
    return this.instance;
  }

}

export const BlazeGAM = BlazeGAMWrapper.getInstance() as BlazeGAMInterface;
