import {
  NativeModulesStatic,
  NativeModules,
} from 'react-native';
import {
  BlazeGAMDelegate,
  BlazeGlobalDelegateHelper
} from './BlazeGAMDelegate';

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?: BlazeGAMDelegate | 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;

}

type KeyValuePair = {
  [key: string]: string;
};

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;

  /**
   * Sets additional custom targeting params into Google's ad request.
   * 
   * @example
    ```typescript
      BlazeGAM.setCustomGAMTargetingProperties({
        key1: 'value1',
        key2: 'value2',
      })
    ```
  * 
  * @param settings - The IMA settings to send to the IMA sdk.
  */
  setCustomGAMTargetingProperties(props?: KeyValuePair): void;
}

interface BlazeGAMInterfaceInternal extends NativeModulesStatic {
  enableCustomNativeAds(
    options: BlazeGAMEnableCustomNativeAdsOptionsNative
  ): void;
  disableCustomNativeAds(): void;
  setCustomGAMTargetingProperties(props: KeyValuePair): 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
    });
    BlazeGlobalDelegateHelper.registerDelegate(options.delegate)
  }

  disableCustomNativeAds(): void {
    BlazeGAMNativeModule.disableCustomNativeAds()
  }

  setCustomGAMTargetingProperties(props: KeyValuePair = {}): void {
    BlazeGAMNativeModule.setCustomGAMTargetingProperties(props)
  }

  // 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;
