import { HTMLAttributes } from 'react';
import { DragAndDropState } from '../DragAndDrop';
import { FiltersMap } from '@wix/bex-core';
import { action } from 'mobx';

export interface DndTestEventHandlersParams<T, F extends FiltersMap> {
  id: string | number;
  disabled?: {
    draggable?: boolean;
    droppable?: boolean;
  };
  state: DragAndDropState<T, F>;
}

export const sortableItemTestEvents = <T, F extends FiltersMap>({
  id,
  disabled,
  state,
}: DndTestEventHandlersParams<T, F>): Partial<HTMLAttributes<HTMLElement>> => {
  return {
    onPointerDown: () => {
      if (disabled?.draggable) {
        return;
      }
      state.onDragStart({ active: { id } });
    },
    onPointerUp: async () => {
      if (disabled?.droppable || state.activeId == null) {
        return;
      }
      const isCancelled = await state.beforeDrop({
        active: {
          id: state.activeId,
        },
        over: {
          id,
        },
      });
      if (isCancelled) {
        return;
      }

      state.onDragEnd({
        over: {
          id,
        },
      });
    },
    onMouseMove: (event) => {
      if (disabled?.droppable || state.activeId == null) {
        return;
      }

      state.onDragMove({
        active: { id: state.activeId },
        delta: {
          x: event.nativeEvent.clientX,
        },
      });

      state.onDragOver({
        over: {
          id,
        },
      });
    },
    onKeyDown: (e) => {
      const keyboardCodes = state.keyboardCodes;

      if (
        state.status === 'start' ||
        (state.status === 'over' &&
          keyboardCodes.move.includes(e.nativeEvent.code))
      ) {
        state.onDragOver({
          over: {
            id,
          },
        });
        return;
      }
    },
  };
};

export const dragHandleTestEvents = <T, F extends FiltersMap>({
  id,
  state,
}: DndTestEventHandlersParams<T, F>): Partial<HTMLAttributes<HTMLElement>> => {
  return {
    onKeyDown: action((e) => {
      state.handleEvents?.onKeyDown?.(e);

      const keyboardCodes = state.keyboardCodes;

      if (state.status === 'start' || state.status === 'over') {
        if (keyboardCodes.end.includes(e.nativeEvent.code)) {
          if (state.activeId == null) {
            return;
          }
          state.beforeDrop({
            active: { id: state.activeId },
            over: { id: state.overId as string },
          });
          state.onDragEnd({ over: { id: state.overId as string } });
          return;
        }

        if (keyboardCodes.cancel.includes(e.nativeEvent.code)) {
          state.onDragCancel();
          return;
        }
      }

      if (keyboardCodes.start.includes(e.nativeEvent.code)) {
        state.onDragStart({ active: { id } });
        return;
      }
    }),
  };
};
