import { Component } from 'react';
import {
  NativeSyntheticEvent,
  UIManager,
  findNodeHandle,
} from 'react-native';
import {
  BlazeBaseWidgetViewProps,
  BlazeSdkBaseWidgetViewProps,
} from './BlazeBaseWidgetViewProps';
import {
  OnDataLoadStartedEvent,
  OnDataLoadCompleteEvent,
  OnPlayerDidAppearEvent,
  OnPlayerDidDismissEvent,
  OnItemClickedEvent,
  OnTriggerCTAEvent,
  OnTriggerPlayerBodyTextLinkEvent,
  OnTriggerCustomActionButtonEvent,
  OnPlayerEventTriggeredEventInternal,
  OnHeightChangedEventInternal,
  BlazeDataSourceType,
  BlazeWidgetOnItemClickedParams,
} from '../interfaces';
import {
  BlazeBasePlayerDelegateHandler,
} from '../classes/base-player-delegate';
import {
  BlazeWidgetItemCustomMapping,
  BlazeWidgetItemStyleOverrides
} from '../classes/blaze-widget-overrides-styles';
import { mapToObject } from '../utils';

export interface State {
  height: number;
}

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

  state = {
    height: 0
  };

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

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

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

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

  private _onItemClicked = (event: NativeSyntheticEvent<OnItemClickedEvent>) => {
    if (this.props.widgetDelegate?.onItemClicked) {
      const params: BlazeWidgetOnItemClickedParams = {
        sourceId: event.nativeEvent.sourceId,
        widgetItemId: event.nativeEvent.widgetItemId,
        widgetItemTitle: event.nativeEvent.widgetItemTitle
      };
      this.props.widgetDelegate.onItemClicked(params);
    }
  };

  private _onTriggerCTA = (event: NativeSyntheticEvent<OnTriggerCTAEvent>) => {
    // Pass the native event directly to the shared handler
    BlazeBasePlayerDelegateHandler.handleTriggerCTA(
      event.nativeEvent,
      this.props.widgetDelegate?.onTriggerCTA
    );
  };

  private _onTriggerPlayerBodyTextLink = (event: NativeSyntheticEvent<OnTriggerPlayerBodyTextLinkEvent>) => {
    // Pass the native event directly to the shared handler
    BlazeBasePlayerDelegateHandler.handleTriggerPlayerBodyTextLink(
      event.nativeEvent,
      this.props.widgetDelegate?.onTriggerPlayerBodyTextLink
    );
  };

  private _onPlayerEventTriggered = (event: NativeSyntheticEvent<OnPlayerEventTriggeredEventInternal>) => {
    BlazeBasePlayerDelegateHandler.handlePlayerEventTriggered(
      event.nativeEvent,
      this.props.widgetDelegate?.onPlayerEventTriggered
    );
  };

  private _onTriggerCustomActionButton = (event: NativeSyntheticEvent<OnTriggerCustomActionButtonEvent>) => {
    BlazeBasePlayerDelegateHandler.handleTriggerCustomActionButton(
      event.nativeEvent,
      this.props.widgetDelegate?.onTriggerCustomActionButton
    );
  };

  private _onHeightChange = (event: NativeSyntheticEvent<OnHeightChangedEventInternal>) => {
    this.setState({
      height: Number(event.nativeEvent.newHeight)
    });
  };

  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,
      onTriggerCustomActionButtonInternal: this._onTriggerCustomActionButton,
      onHeightChangedInternal: this._onHeightChange,
    };

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

  shouldComponentUpdate(
    nextProps: Readonly<PROPS>,
    nextState: Readonly<State>,
    nextContext: any): boolean {

    // Allow Re-render if state has changed (Contains the widget's height)
    const hasStateChanged = this.state != nextState
    if (hasStateChanged)
      return true

    // ATM we don't re-render in any other case - because ReactNative sometimes render multiple times and the shimmer animation is glitched.
    return false
  }

}
