import * as React from 'react';

import { UITrackingPayload } from 'mweb/common/actions/tracking';
import { TrackingContext } from 'mweb/common/tracking/trackingProvider';
import {
  ContextTypes,
  contextTypeValidator,
} from 'mweb/common/utils/contextTypeValidator';
import { getComponentName } from 'mweb/common/utils/getComponentName';

export interface TrackingInteractionContentProps
  extends Pick<UITrackingPayload, 'interactionContent'> {}

export type UITrackingParameters = ObjectOmit<
  UITrackingPayload,
  'interactionMedium'
>;

export type TrackClickHandler = (
  payload: UITrackingParameters,
  callback?: React.EventHandler<React.MouseEvent<any>>,
) => (e?: React.MouseEvent<any>) => void;

export interface TrackingProps {
  trackClick: TrackClickHandler;
}

export function withTracking<P extends TrackingProps>(
  WrappedComponent: React.ComponentType<P>,
): React.ComponentType<ObjectDiff<P, TrackingProps>> {
  return class Trackable extends React.Component<
    ObjectDiff<P, TrackingProps>,
    {}
  > {
    static displayName: string = `Trackable(${getComponentName(
      WrappedComponent,
    )})`;

    static contextTypes: ContextTypes<TrackingContext> = {
      trackingTrackClick: contextTypeValidator,
      interactionMedium: contextTypeValidator,
    };

    context: TrackingContext;

    trackClick = (
      payload: UITrackingParameters,
      onClickHandler?: React.EventHandler<React.MouseEvent<any>>,
    ) => (e: React.MouseEvent<any>) => {
      this.context.trackingTrackClick({
        ...payload,
        interactionMedium: this.context.interactionMedium,
      });
      if (onClickHandler) {
        onClickHandler(e);
      }
    };

    render(): JSX.Element {
      return <WrappedComponent {...this.props} trackClick={this.trackClick} />;
    }
  };
}
