import styled from '@emotion/styled';
import { useCallback, useEffect, useRef, useState } from 'react';

import useClickDrag from '@/hooks/useClickDrag';

const Wrapper = styled.div`
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: -1px;
  right: -1px;
  border-radius: 12px;
`;

const ExtendFromGrabber = styled.div<{ dragging: boolean }>`
  pointer-events: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 12px;
  background-color: var(--color-accent-brand);
  border-top-right-radius: 11px;
  border-bottom-right-radius: 11px;
  opacity: 1;
  transition: opacity 0.15s ease-in-out;
  cursor: ew-resize;
  z-index: 1;
  box-shadow: 0 0 0 1px var(--color-accent-brand);
  &:after {
    content: '';
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    left: -10px;
    right: -10px;
    z-index: 2;
  }
`;

const WaveformWrapper = styled.div`
  position: relative;
  width: calc(100% + 2px);
  height: calc(100% + 2px);
  margin: -1px;
  border-radius: 12px;
`;

const ExtendRadiusWrapper = styled.div`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  border-radius: 12px;
  overflow: hidden;
`;

const ExtendFromOverlayWrapper = styled.div`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  border: 1px solid var(--color-accent-brand);
  border-radius: 12px;
`;

const DimmedOverlay = styled.div`
  position: absolute;
  top: 2px;
  bottom: 2px;
  right: 2px;
  border-radius: 10px;
  background-color: var(--color-background-secondary);
  opacity: 0.7;
  pointer-events: none;
  z-index: 0;
`;

export const ExtendFromOverlay = ({
  minExtendFromProgress,
  extendFromProgress,
  setExtendFromProgress,
  onDragUpdate,
}: {
  minExtendFromProgress: number;
  extendFromProgress: number;
  setExtendFromProgress: (progress: number) => void;
  onDragUpdate?: (progress: number) => void;
}) => {
  const [dragging, setDragging] = useState(false);
  const [grabberPosition, setGrabberPosition] = useState(
    Math.max(minExtendFromProgress, extendFromProgress)
  );

  useEffect(() => {
    if (dragging) return;
    requestAnimationFrame(() => {
      setGrabberPosition(Math.max(minExtendFromProgress, extendFromProgress));
    });
  }, [extendFromProgress, dragging, minExtendFromProgress]);

  const wrapperRef = useRef<HTMLDivElement>(null);
  const clickDragRef = useClickDrag(
    useCallback(() => {
      const wrapper = wrapperRef.current;
      if (!wrapper) return;
      const rect = wrapper.getBoundingClientRect();

      setDragging(true);
      onDragUpdate?.(grabberPosition);
      return {
        onMouseMove: ({ deltaXFromStart }) => {
          const deltaProgress = deltaXFromStart / rect.width;
          const newProgress = Math.max(
            minExtendFromProgress,
            Math.min(1, grabberPosition + deltaProgress)
          );
          setGrabberPosition(newProgress);
          onDragUpdate?.(newProgress);
        },
        onMouseUp: ({ deltaXFromStart }) => {
          const deltaProgress = deltaXFromStart / rect.width;
          const newProgress = Math.max(
            minExtendFromProgress,
            Math.min(1, grabberPosition + deltaProgress)
          );
          setGrabberPosition(newProgress);
          setExtendFromProgress(newProgress);
          setDragging(false);
        },
      };
    }, [
      grabberPosition,
      setExtendFromProgress,
      onDragUpdate,
      minExtendFromProgress,
    ])
  );

  return (
    <Wrapper>
      <WaveformWrapper ref={wrapperRef}>
        <ExtendRadiusWrapper>
          <ExtendFromOverlayWrapper
            style={{ right: `${(1 - grabberPosition) * 100}%` }}
            className='extend-control-wrapper'
          >
            {!dragging && (
              <ExtendFromGrabber
                ref={clickDragRef}
                dragging={dragging}
                className='extend-from-grabber'
              />
            )}
          </ExtendFromOverlayWrapper>
          <DimmedOverlay
            style={{
              left: `calc(${grabberPosition * 100}% - ${dragging ? 0 : 12}px)`,
            }}
          />
        </ExtendRadiusWrapper>
      </WaveformWrapper>
    </Wrapper>
  );
};
