import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Scrollbars } from 'react-custom-scrollbars';
import { Container, Draggable } from 'react-smooth-dnd';
import { useEventListener } from '@devesharp/react-hooks';
import { IImagesSortableContainerProps } from '../../ImageSortable';
import * as S from './DNDContainer.style';

export interface IDNDContainerProps {
   items: { [key: string]: any; id: string | number; items: { [key: string]: any; id: string | number }[] }[];
   onChange: (
      newItems: any[],
      currentIndex: { index: number; step: number },
      oldIndex: { index: number; step: number },
      resource: any,
   ) => void;
   renderCard: (props: { data: any; dragging: boolean; dragOverlay: boolean; disabled: boolean; index: number }) => any;
}

export const DNDGroupContainer = React.memo(function DNDGroupContainer(props: any) {
   const { onChange, items } = props;

   function onDrop(): void {}

   function onDragStart(): void {}

   function onDragEnd(): void {}

   return (
      <>
         {items.map((step: any, stepIndex: number) => (
            <Step
               key={`step-${step.id}`}
               index={stepIndex}
               step={step}
               onDrop={onDrop}
               enableAutoScroll
               onDragStart={onDragStart}
               onDragEnd={onDragEnd}
            />
         ))}
      </>
   );
});

export function Step({ id, index, groupName, step, onDrop, onDragStart, onDragEnd, renderCard }: any): any {
   const ScrollbarsRef = useRef<any>(null);
   const [enableAutoScroll, setEnableAutoScroll] = useState(false);

   useScrollAnimationDragWithScrollbars(ScrollbarsRef, enableAutoScroll);

   function _onDrop(e, i): void {
      if (onDrop) onDrop(e, i);
   }

   function _onDragStart(): void {
      setEnableAutoScroll(true);
      if (onDragStart) onDragStart();
   }

   function _onDragEnd(): void {
      setEnableAutoScroll(false);
      if (onDragEnd) onDragEnd();
   }

   return (
      <Scrollbars className="steps-card-listing--inner" autoHide ref={ScrollbarsRef}>
         <Container
            groupName={groupName}
            onDrop={(e) => _onDrop(e, index)}
            onDragStart={() => _onDragStart()}
            onDragEnd={() => _onDragEnd()}
            animationDuration={200}
            getChildPayload={(i) => step.items[i]}
            dropPlaceholder={{
               animationDuration: 150,
               showOnTop: true,
               className: 'drop-preview',
            }}
            autoScrollEnabled={false}
            dragClass="card-ghost"
            dropClass="card-ghost-drop"
         >
            {step.items.map((lead: any, leadIndex) => (
               <Draggable key={lead.id}>{renderCard(lead)}</Draggable>
            ))}
         </Container>
      </Scrollbars>
   );
}

export function useScrollAnimationDragWithScrollbars(ref: any, enabled = false): void {
   const lastTime = useRef(Date.now());
   const moveX = useRef(false);
   const factorX = useRef(0);
   const factorY = useRef(0);
   const borderFactor = 0.1;

   useEventListener('mousemove', (ev: any) => {
      const mouseX = ev.clientX;
      const mouseY = ev.clientY;

      const offsetLeft = ref.current.container.getBoundingClientRect().x;
      const offsetTop = ref.current.container.getBoundingClientRect().y;
      const width = ref.current.getClientWidth();
      const height = ref.current.getClientHeight();

      if (offsetLeft + width * 0.1 > mouseX) {
         let factor = 1 - (mouseX - offsetLeft) / (width * 0.1);
         factor = factor > 1 ? 1 : factor;
         factor = factor < 0 ? 0 : factor;
         factorX.current = -factor;
      } else if (mouseX > offsetLeft + width - width * 0.1) {
         let factor = 1 - (offsetLeft + width - mouseX) / (width * 0.1);
         factor = factor > 1 ? 1 : factor;
         factor = factor < 0 ? 0 : factor;
         factorX.current = factor;
      } else {
         factorX.current = 0;
      }

      if (mouseX >= offsetLeft && mouseX <= offsetLeft + width) {
         if (offsetTop + height * 0.1 > mouseY) {
            let factor = 1 - (mouseY - offsetTop) / (height * 0.1);
            factor = factor > 1 ? 1 : factor;
            factor = factor < 0 ? 0 : factor;
            factorY.current = -factor;
         } else if (mouseY > offsetTop + height - height * 0.1) {
            let factor = 1 - (offsetTop + height - mouseY) / (height * 0.1);
            factor = factor > 1 ? 1 : factor;
            factor = factor < 0 ? 0 : factor;
            factorY.current = factor;
         } else {
            factorY.current = 0;
         }
      }
   });

   useEffect(() => {
      if (enabled) {
         lastTime.current = Date.now();
         const interval = setInterval(() => {
            const timeLapse = Date.now() - lastTime.current;
            lastTime.current = Date.now();

            const animationSize = (timeLapse / 1000) * 500;
            if (factorX.current) {
               ref.current.scrollLeft(ref.current.getScrollLeft() + factorX.current * animationSize);
            }

            if (factorY.current) {
               ref.current.scrollTop(ref.current.getScrollTop() + factorY.current * animationSize);
            }
         }, 50);

         return () => clearInterval(interval);
      }
   }, [enabled]);
}
