import { ReactNode, useEffect, useRef, useState } from 'react';
import type { EditorState } from 'lexical';
import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
import { ClearEditorPlugin } from '@lexical/react/LexicalClearEditorPlugin';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { HorizontalRulePlugin } from '@lexical/react/LexicalHorizontalRulePlugin';
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { TabIndentationPlugin } from '@lexical/react/LexicalTabIndentationPlugin';
import { TablePlugin } from '@lexical/react/LexicalTablePlugin';

import './rich-text-editor.css';
import './plugins/FloatingLinkEditorPlugin/index.css';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';

import { SharedHistoryContext, useSharedHistoryContext } from './context/SharedHistoryContext';
import { I18nProvider, SupportedLanguages } from './i18n';
import type { I18N } from './i18n/types';
import { composeInitialState } from './model/crystallize-to-lexical';
import { lexicalToCrystallizeRichText } from './model/lexical-to-crystallize';
import { BaseNodes } from './nodes/BaseNodes';
import AutoLinkPlugin from './plugins/AutoLinkPlugin';
import CodeActionMenuPlugin from './plugins/CodeActionMenuPlugin';
import CodeHighlightPlugin from './plugins/CodeHighlightPlugin';
import FloatingLinkEditorPlugin from './plugins/FloatingLinkEditorPlugin';
import FloatingTextFormatToolbarPlugin from './plugins/FloatingTextFormatToolbarPlugin';
import LinkPlugin from './plugins/LinkPlugin';
import ListMaxIndentLevelPlugin from './plugins/ListMaxIndentLevelPlugin';
import { MaxLengthPlugin } from './plugins/MaxLengthPlugin';
import TabFocusPlugin from './plugins/TabFocusPlugin';
import TableCellActionMenuPlugin from './plugins/TableActionMenuPlugin';
import ToolbarPlugin from './plugins/ToolbarPlugin';
import CrystallizeRTEditorTheme from './themes/CrystallizeRTEditorTheme';
import type { CrystallizeRichText } from './types/crystallize-rich-text-types';
import type { CrystallizeRichTextActionMenuItem } from './types/types';

/**
 * Currently disabling this as there is a conflict with someting within
 * the app. @hk have done 15minutes of debugging without finding out what
 * causes the conflict. We can re-visit this at some later time.
 */
// import DraggableBlockPlugin from './plugins/DraggableBlockPlugin';

type TRichTextBase = {
  placeholder?: string;
  onChange?: (data: CrystallizeRichText) => void;
  triggerOnChangeOnAutoFocus?: boolean;
  autoFocus?: boolean;
  actionsMenuPrepend?: CrystallizeRichTextActionMenuItem[];
  actionsMenuAppend?: CrystallizeRichTextActionMenuItem[];
  slotPreContent?: ReactNode;
  maxLength?: number;
  language?: SupportedLanguages;
  labelTranslations?: I18N;
  id?: string;
  disabled?: boolean;
};

export function RichTextEditor({
  initialData,
  language = 'en',
  labelTranslations,
  ...rest
}: TRichTextBase & {
  initialData?: CrystallizeRichText | null;
}) {
  return (
    <LexicalComposer
      initialConfig={{
        editable: !rest.disabled,
        namespace: 'crystallize-rich-text-editor',
        nodes: [...BaseNodes],
        theme: CrystallizeRTEditorTheme,
        editorState: initialData ? composeInitialState({ richText: initialData }) : undefined,
        onError: (error: Error) => {
          throw error;
        },
      }}
    >
      <I18nProvider language={language} labelTranslations={labelTranslations}>
        <SharedHistoryContext>
          <div className="c-rich-text-editor">
            <RichTextEditorWithoutContext {...rest} />
          </div>
        </SharedHistoryContext>
      </I18nProvider>
    </LexicalComposer>
  );
}

function RichTextEditorWithoutContext({
  placeholder: placeholderText,
  onChange,
  triggerOnChangeOnAutoFocus,
  autoFocus,
  actionsMenuPrepend,
  actionsMenuAppend,
  slotPreContent,
  maxLength,
  disabled,
  id,
}: TRichTextBase): JSX.Element {
  const editable = !disabled;
  const { historyState } = useSharedHistoryContext();
  const placeholder = <div className="c-rte-placeholder">{placeholderText ?? ''}</div>;

  const [editor] = useLexicalComposerContext();
  const [floatingAnchorElem, setFloatingAnchorElem] = useState<HTMLDivElement | null>(null);
  const firstOnChangeTriggeredRef = useRef(!autoFocus);

  const onRef = (_floatingAnchorElem: HTMLDivElement) => {
    if (_floatingAnchorElem !== null) {
      setFloatingAnchorElem(_floatingAnchorElem);
    }
  };

  // Listen for editable change
  useEffect(() => {
    editor.setEditable(editable || false);
  }, [editable, editor]);

  function onLocalChange(editorState: EditorState) {
    if (onChange) {
      if (triggerOnChangeOnAutoFocus || firstOnChangeTriggeredRef.current) {
        onChange(lexicalToCrystallizeRichText({ editor, editorState }));
      }
    }

    firstOnChangeTriggeredRef.current = true;
  }

  return (
    <>
      <OnChangePlugin onChange={onLocalChange} ignoreSelectionChange />
      <ToolbarPlugin
        disabled={disabled}
        actionsMenuPrepend={actionsMenuPrepend}
        actionsMenuAppend={actionsMenuAppend}
      />
      {slotPreContent}
      <div className={`c-rte-editor-container ${disabled ? 'disabled' : ''}`} data-testid="rich-text-editor">
        {maxLength != null ? <MaxLengthPlugin maxLength={maxLength} /> : null}
        {!autoFocus ? null : <AutoFocusPlugin />}
        <ClearEditorPlugin />
        <AutoLinkPlugin />

        <HistoryPlugin externalHistoryState={historyState} />

        <RichTextPlugin
          contentEditable={
            <div className="c-rte-editor-scroller">
              <div className="c-rte-editor" ref={onRef}>
                <ContentEditable className="c-rte-contenteditable-root" id={id} />
              </div>
            </div>
          }
          placeholder={placeholder}
          ErrorBoundary={LexicalErrorBoundary}
        />
        <CodeHighlightPlugin />
        <ListPlugin />
        <ListMaxIndentLevelPlugin maxDepth={7} />
        <TablePlugin />
        <LinkPlugin />
        <HorizontalRulePlugin />
        <TabFocusPlugin />
        <TabIndentationPlugin />
        {floatingAnchorElem && (
          <>
            {/* <DraggableBlockPlugin anchorElem={floatingAnchorElem} /> */}
            <CodeActionMenuPlugin anchorElem={floatingAnchorElem} />
            <FloatingLinkEditorPlugin anchorElem={floatingAnchorElem} />
            <TableCellActionMenuPlugin anchorElem={floatingAnchorElem} />
            <FloatingTextFormatToolbarPlugin anchorElem={floatingAnchorElem} />
          </>
        )}
      </div>
    </>
  );
}

export default RichTextEditor;
