import React from 'react';
import { observer } from 'mobx-react';
import { CSSProperties, css } from 'glamor';
import { dragSelect } from './dragSelect';
import { ApphouseComponent } from '../component.interfaces';
import { useLocalStyles } from '../../styles/defaults/useLocalStyles';

/**
 * Interface for the styles of the Draggable component
 */
export interface DraggableStyles {
  container?: CSSProperties;
  dragging?: CSSProperties;
}

/**
 * Interface for the Draggable component props
 */
export interface DraggableProps extends ApphouseComponent<DraggableStyles> {
  /**
   * The id of the draggable, must be unique to the app
   */
  id: string;
  /**
   * The index of the draggable item
   */
  index: number;
  /**
   * The function to call when the draggable is dropped
   */
  onDrop: () => void;
  /**
   * Whether the draggable is disabled
   * @default false
   * @optional
   */
  disabled?: boolean;
  /**
   * The children of the draggable
   */
  children: React.ReactNode;
}

/**
 * A draggable component
 * @param props DraggableProps
 */
export const Draggable = observer((props: DraggableProps) => {
  const {
    disabled = false,
    id,
    index,
    children,
    onDrop,
    styleOverwrites,
    gutters
  } = props;

  const componentStyles = {
    container: {
      position: 'relative'
    },
    dragging: {
      userSelect: 'none',
      cursor: 'grab',
      transition: 'opacity 0.1s linear'
    }
  };

  const localStyles = useLocalStyles<DraggableStyles>(
    componentStyles,
    styleOverwrites,
    gutters
  );
  return (
    <div
      {...css(localStyles.container)}
      data-style="container"
      data-xray="draggable"
    >
      <div
        data-style="dragging"
        draggable={!disabled}
        onDragStart={(e) => {
          if (!disabled) {
            dragSelect.setDragType('moving');
            const draggedElement: HTMLElement = e.target as HTMLElement;
            const parentElement = draggedElement.parentElement;

            if (parentElement !== null) {
              const dimensions = parentElement?.getBoundingClientRect();
              e.dataTransfer.setDragImage(parentElement, 0, 0);

              const w = dimensions?.width;
              const h = dimensions?.height;
              dragSelect.setDraggingId(id);
              dragSelect.setDimensionValues(w, h);

              dragSelect.setDraggingItemListIndex(index);
            }
          }
        }}
        onDragOver={() => {
          if (!disabled) {
            dragSelect.setDropAtIndex(index);
          }
        }}
        onDrop={onDrop}
        {...css(localStyles.dragging)}
      >
        {children}
      </div>
    </div>
  );
});
