import {
  NativeSyntheticEvent,
  UIManager,
  findNodeHandle
} from 'react-native';

import {
  Component
} from 'react';

import {
  BlazeDataSourceType,
  OnDataLoadStartedEvent,
  OnDataLoadCompleteEvent,
  OnPlayerDidAppearEvent,
  OnPlayerDidDismissEvent,
  OnItemClickedEvent,
  OnTriggerCTAEvent,
  OnTriggerPlayerBodyTextLinkEvent,
  OnPlayerEventTriggeredEventInternal,
} from '../interfaces';

import {
  BlazeWidgetItemCustomMapping,
  BlazeWidgetItemStyleOverrides
} from "../classes/blaze-widget-overrides-styles"

import { mapToObject } from '../utils';

import {
  BlazeBaseWidgetViewProps,
  BlazeSdkBaseWidgetViewProps
} from './BlazeBaseWidgetViewProps';
import { CommonParser } from '../classes/common-parser';

export class BlazeBaseWidgetView
  <PROPS extends BlazeBaseWidgetViewProps> extends Component<PROPS> {
  protected ref?: Component<BlazeSdkBaseWidgetViewProps, {}, any>;

  private _onDataLoadStarted = (event: NativeSyntheticEvent<OnDataLoadStartedEvent>) => {
    if (this.props.widgetDelegate?.onDataLoadStarted) {
      this.props.widgetDelegate?.onDataLoadStarted(event.nativeEvent);
    }
  };

  private _onDataLoadCompleted = (event: NativeSyntheticEvent<OnDataLoadCompleteEvent>) => {
    if (this.props.widgetDelegate?.onDataLoadComplete) {
      this.props.widgetDelegate?.onDataLoadComplete(event.nativeEvent);
    }
  };

  private _onPlayerDidAppear = (event: NativeSyntheticEvent<OnPlayerDidAppearEvent>) => {
    if (this.props.widgetDelegate?.onPlayerDidAppear) {
      this.props.widgetDelegate?.onPlayerDidAppear(event.nativeEvent);
    }
  };

  private _onPlayerDismiss = (event: NativeSyntheticEvent<OnPlayerDidDismissEvent>) => {
    if (this.props.widgetDelegate?.onPlayerDidDismiss) {
      this.props.widgetDelegate?.onPlayerDidDismiss(event.nativeEvent);
    }
  };

  private _onItemClicked = (event: NativeSyntheticEvent<OnItemClickedEvent>) => {
    if (this.props.widgetDelegate?.onItemClicked) {
      this.props.widgetDelegate?.onItemClicked(event.nativeEvent);
    }
  };

  private _onTriggerCTA = (event: NativeSyntheticEvent<OnTriggerCTAEvent>) => {
    if (this.props.widgetDelegate?.onTriggerCTA) {
      this.props.widgetDelegate?.onTriggerCTA(event.nativeEvent);
    }
  };

  private _onTriggerPlayerBodyTextLink = (event: NativeSyntheticEvent<OnTriggerPlayerBodyTextLinkEvent>) => {
    if (this.props.widgetDelegate?.onTriggerPlayerBodyTextLink) {
      this.props.widgetDelegate?.onTriggerPlayerBodyTextLink(event.nativeEvent);
    }
  };
  private _onPlayerEventTriggered = (event: NativeSyntheticEvent<OnPlayerEventTriggeredEventInternal>) => {
    if (this.props.widgetDelegate?.onPlayerEventTriggered) {
      const nativeEvent = event.nativeEvent
      const widgetId = nativeEvent.widgetId
      const playerEventType = nativeEvent.playerEventType
      const playerEventParams = nativeEvent.playerEventParams

      const result = CommonParser.extractPlayerEvent(playerEventType, playerEventParams)

      if (result != null) {
        this.props.widgetDelegate?.onPlayerEventTriggered({
          widgetId: widgetId,
          playerEvent: result
        });
      }
    }
  };

  public reloadData(isSilentRefresh: Boolean = false) {
    if (this.ref) {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(this.ref),
        UIManager.getViewManagerConfig(this.getComponentName()).Commands.reloadData,
        [isSilentRefresh],
      );
    }
  }

  public updateDataSource(
    dataSource: BlazeDataSourceType,
    isSilentRefresh: Boolean = false
  ) {
    if (this.ref) {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(this.ref),
        UIManager.getViewManagerConfig(this.getComponentName()).Commands.updateDataSource,
        [dataSource, isSilentRefresh]
      );
    }
  }

  public play() {
    if (this.ref) {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(this.ref),
        UIManager.getViewManagerConfig(this.getComponentName()).Commands.play
      );
    }
  }

  public updateOverrideStyles(
    perItemStyleOverrides: Map<BlazeWidgetItemCustomMapping, BlazeWidgetItemStyleOverrides>,
    shouldUpdateUi: boolean
  ) {
    if (this.ref) {

      const perItemStyleOverridesRecord = mapToObject(perItemStyleOverrides);

      UIManager.dispatchViewManagerCommand(
        findNodeHandle(this.ref),
        UIManager.getViewManagerConfig(this.getComponentName()).Commands.updateOverrideStyles,
        [perItemStyleOverridesRecord, shouldUpdateUi]
      );

    }
  }

  public updateWidgetsUi() {
    if (this.ref) {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(this.ref),
        UIManager.getViewManagerConfig(this.getComponentName()).Commands.updateWidgetsUi,
      );
    }
  }

  // This method should be overridden by derived components
  protected getComponentName(): string {
    throw new Error('getComponentName() not implemented');
  }

  protected createBaseProps(): BlazeSdkBaseWidgetViewProps {
    const baseProps: BlazeSdkBaseWidgetViewProps = {
      ...this.props,
      onWidgetDataLoadStartedInternal: this._onDataLoadStarted,
      onWidgetDataLoadCompletedInternal: this._onDataLoadCompleted,
      onWidgetPlayerDidAppearInternal: this._onPlayerDidAppear,
      onWidgetPlayerDismissedInternal: this._onPlayerDismiss,
      onItemClickedInternal: this._onItemClicked,
      onTriggerCTAInternal: this._onTriggerCTA,
      onTriggerPlayerBodyTextLinkInternal: this._onTriggerPlayerBodyTextLink,
      onPlayerEventTriggeredInternal: this._onPlayerEventTriggered,
    };

    // If perItemStyleOverrides is defined and is a Map, convert it to an object
    if (this.props.perItemStyleOverrides instanceof Map) {
      baseProps.perItemStyleOverridesInternal = mapToObject(this.props.perItemStyleOverrides);
    }

    return baseProps;
  }

}
