import React, { useRef, useState, useEffect, useCallback } from 'react';
import {
  useValueDebounce,
  CodeSnippet,
  useHover,
} from '@knapsack/design-system';
import ReactMarkdown from 'react-markdown';
import { Slice, SliceRenderParams } from './types';
import { SuspenseLoader } from '../../../components/suspense-loader';
import 'easymde/dist/easymde.min.css';
import './markdown-slice.scss';

// https://github.com/RIP21/react-simplemde-editor
const SimpleMDE = React.lazy(() => import('react-simplemde-editor'));

type Data = {
  md: string;
};

type Props = SliceRenderParams<Data>;

const MarkdownSlice: React.FC<Props> = ({
  canEdit,
  setSliceData,
  data,
}: Props) => {
  const markdownSliceDiv = useRef(null);
  const [isEditorShown, setEditorShown] = useState(false);

  // Detect outside clicks when editor is shown and
  // hide the editor.
  const onGeneralClick = useCallback(
    (e: MouseEvent) => {
      const isOutsideClick = !markdownSliceDiv.current.contains(
        e.target as Node,
      );

      if (isOutsideClick) {
        setEditorShown(false);
        window.removeEventListener('click', onGeneralClick);
      }
    },
    [markdownSliceDiv],
  );

  // Figure out how to clean this up on unmount.
  useEffect(() => {
    return function cleanup() {
      window.removeEventListener('click', onGeneralClick);
    };
  }, [onGeneralClick]);

  type OnTriggerEvent =
    | React.MouseEvent<HTMLDivElement, MouseEvent>
    | React.KeyboardEvent<HTMLDivElement>;

  // Turns on edit mode, but not if click was on a link.
  const onClickSlice = (event: OnTriggerEvent) => {
    let isLink = false;

    if (event) {
      // Uncomment to be able to console log 'event'.
      // event.persist();

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const target = event.target as any;
      isLink = target?.nodeName === 'A';

      // We decided to open a new tab when clicking a link in
      // these markdown slices. Might need to revisit.
      if (isLink && target?.href) {
        event.preventDefault();
        window.open(target.href, '_blank');
      }
    }

    if (canEdit && !isEditorShown && !isLink) {
      setEditorShown(true);

      // Timeout forces the listener to add on the next tick and
      // not fire the function immediately.
      setTimeout(() => {
        window.addEventListener('click', onGeneralClick);
      }, 0);
    }
  };

  return (
    <div
      className="markdown-slice"
      ref={markdownSliceDiv}
      role="button"
      tabIndex={0}
      onClick={onClickSlice}
      onKeyDown={onClickSlice}
    >
      {isEditorShown && (
        <SuspenseLoader>
          <SimpleMDE
            onChange={md => setSliceData({ md })}
            value={data?.md || ''}
            // https://github.com/Ionaru/easy-markdown-editor#configuration
            options={{
              indentWithTabs: false,
              promptURLs: true,
              spellChecker: false,
              minHeight: '22px',
              placeholder: 'Enter markdown content...',
              status: false,
            }}
          />
        </SuspenseLoader>
      )}
      {!isEditorShown && (
        <ReactMarkdown
          // TODO: create better placeholder text.. probably delete on blur.
          source={
            data && data.md ? data.md.trim() : 'No text has been entered...'
          }
          renderers={{
            code: ({ language, value }) => (
              <CodeSnippet code={value} language={language} />
            ),
          }}
        />
      )}
    </div>
  );
};

export const markdownSlice: Slice<Data> = {
  id: 'markdown-slice',
  title: 'Text',
  render: props => <MarkdownSlice {...props} />,
};
