import styled from '@emotion/styled';
import React, { ForwardedRef, forwardRef, useCallback } from 'react';

export const updateAfterScroll = (
  editorContentRef: React.RefObject<HTMLDivElement>,
  selectionFollowerRef: React.RefObject<HTMLDivElement>
) => {
  const editorContent = editorContentRef.current;
  const selectionFollower = selectionFollowerRef.current;
  if (!selectionFollower || !editorContent) return;
  selectionFollower.style.transform = `translateY(${-1 * editorContent.scrollTop}px)`;
};

export const updateAfterSelectionChange = (
  selectionRect: DOMRect,
  selectionFollowerRef: React.RefObject<HTMLDivElement | null>,
  scrollTop: number
) => {
  const selectionFollower = selectionFollowerRef.current;
  if (!selectionFollower) return;
  const parentRect = selectionFollower.parentElement!.getBoundingClientRect();
  const topOffset = parentRect.top + 20;

  selectionFollower.style.top = `${selectionRect.top + topOffset}px`;
  selectionFollower.style.height = selectionRect.height + 'px';
  selectionFollower.style.transform = `translateY(${-1 * scrollTop}px)`;

  const rewriteUI = selectionFollower.querySelector(
    '.children-container'
  ) as HTMLDivElement | null;
  if (!rewriteUI) return;

  const selectionMiddle =
    selectionRect.top + topOffset - scrollTop + selectionRect.height / 2;
  const rewriteUITop = selectionMiddle - rewriteUI.offsetHeight / 2;
  const rewriteUIBottom = rewriteUITop + rewriteUI.offsetHeight;
  const maxBottom = parentRect.height - 64;
  let formOffset = 0;
  if (rewriteUITop < 0) {
    formOffset = -1 * rewriteUITop;
  } else if (rewriteUIBottom > maxBottom) {
    formOffset = maxBottom - rewriteUIBottom;
  }

  if (formOffset === 0) {
    rewriteUI.style.transform = ``;
  } else {
    rewriteUI.style.transform = `translateY(calc(-50% + ${formOffset}px))`;
  }
};

const SelectionFollowerWrapper = styled.div<{
  emphasizeSelection: boolean;
  obscureSelection: boolean;
}>`
  position: absolute;
  right: 0;
  left: 0;
  z-index: 2;
  transition:
    height 0.1s ease,
    top 0.1s ease;
  .bracket {
    border: 2px solid #f172a4;
    position: absolute;
    width: 10px;
  }
  .top-right-corner.bracket {
    border-bottom-width: 0;
    border-right-width: 0;
    top: 0;
    bottom: 75%;
    right: 0;
    border-top-left-radius: 20px;
  }
  .top-left-corner.bracket {
    border-top-width: 0;
    border-left-width: 0;
    top: 25%;
    bottom: calc(50% - 1px);
    right: 8px;
    border-bottom-right-radius: 20px;
  }
  .bottom-left-corner.bracket {
    border-bottom-width: 0;
    border-left-width: 0;
    top: calc(50% - 1px);
    bottom: 25%;
    right: 8px;
    border-top-right-radius: 20px;
  }
  .bottom-right-corner.bracket {
    border-top-width: 0;
    border-right-width: 0;
    bottom: 0;
    top: 75%;
    right: 0;
    border-bottom-left-radius: 20px;
  }
  .rewrite-overlay {
    position: absolute;
    pointer-events: none;
    opacity: ${({ emphasizeSelection }) => (emphasizeSelection ? 1 : 0)};
    background-color: #f172a444;
    left: 100%;
    width: 100vw;
    height: 100%;
    z-index: 10;
    transition:
      opacity 0.2s ease,
      backdrop-filter 0.2s ease;
    backdrop-filter: ${({ obscureSelection }) =>
      obscureSelection ? 'blur(7px)' : 'blur(0)'};
  }
  .children-container {
    position: absolute;
    right: 18px;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
  }
`;

const SelectionFollower = forwardRef(function SelectionFollower(
  {
    obscureSelection,
    emphasizeSelection,
    hide,
    children,
  }: {
    obscureSelection: boolean;
    emphasizeSelection: boolean;
    hide?: boolean;
    children: React.ReactNode[] | React.ReactNode;
  },
  ref: ForwardedRef<HTMLDivElement>
) {
  const wrapperRef = React.useRef<HTMLDivElement>(null);
  const receiveWrapperRef = useCallback(
    (node: HTMLDivElement) => {
      wrapperRef.current = node;
      if (typeof ref === 'function') {
        ref(node);
      } else if (ref) {
        (ref as React.MutableRefObject<HTMLDivElement>).current = node;
      }
    },
    [ref]
  );

  return (
    <SelectionFollowerWrapper
      ref={receiveWrapperRef}
      obscureSelection={obscureSelection}
      emphasizeSelection={emphasizeSelection}
    >
      {!hide && (
        <>
          <div className='bracket top-right-corner' />
          <div className='bracket top-left-corner' />
          <div className='bracket bottom-left-corner' />
          <div className='bracket bottom-right-corner' />
          <div className='rewrite-overlay' />
        </>
      )}
      <div className='children-container'>{children}</div>
    </SelectionFollowerWrapper>
  );
});

export default SelectionFollower;
