/**
 * This configuration was generated using the CKEditor 5 Builder. You can modify it anytime using this link:
 * https://ckeditor.com/ckeditor-5/builder/#installation/NodgNARATAdCMA4KQMwgVArANiwRgRDwE4UUAWEbTEYqABmQgFMA7ZesYPMTzn/gF1ICAEYAzAIZ5soiIKA=
 */
import { useImperativeHandle, useRef, forwardRef, useState, type ReactElement } from 'react';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import {
  ClassicEditor,
  Autosave,
  Essentials,
  Paragraph,
  GeneralHtmlSupport,
  Bold,
  Italic,
  Heading,
  Link,
  AutoLink,
  BlockQuote,
  List,
  Markdown,
  type EventInfo,
} from 'ckeditor5';
import type { EditorConfig, Editor } from 'ckeditor5';
import 'ckeditor5/ckeditor5.css';
import './TextEditor.css';

export interface EditorHandle {
  setText: (text: string) => void;
  getText: () => string;
}

const TextEditor = forwardRef<
  EditorHandle,
  {
    initialText?: string;
    labelId?: string;
    onChange?: (text: string) => void;
    overlay?: ReactElement | null;
  }
>(({ initialText = '', labelId, onChange = () => {}, overlay = null }, ref) => {
  const [editorConfigWithInitialData] = useState(() => ({
    ...editorConfig,
    initialData: initialText,
  }));
  const editorRef = useRef<Editor | null>(null);

  useImperativeHandle(ref, () => ({
    setText: (text: string) => {
      if (editorRef.current) {
        editorRef.current.setData(text);
      }
    },
    getText: () => {
      return editorRef.current?.getData() || '';
    },
  }));

  const editorReady = (editor: Editor) => {
    // Override italic command to use <em> instead of <i>.
    editor.conversion.for('downcast').attributeToElement({
      model: 'italic',
      view: 'em',
      converterPriority: 'high',
    });

    // Get the editable element and associate it with the label.
    if (labelId) {
      const editableElement = editor.ui.view.editable.element;
      if (editableElement) {
        editableElement.setAttribute('aria-labelledby', labelId);
      }
    }

    editorRef.current = editor;
  };

  const editorChange = (_event: EventInfo, editor: Editor) => {
    const data = editor.getData();

    if (onChange && !!editorRef.current) {
      onChange(data);
    }
  };

  return (
    <div className="text-editor">
      <CKEditor
        editor={ClassicEditor}
        config={editorConfigWithInitialData}
        onReady={editorReady}
        onChange={editorChange}
      />
      {overlay && <div className="text-editor__overlay">{overlay}</div>}
    </div>
  );
});

const editorConfig: EditorConfig = {
  toolbar: {
    items: [
      'heading',
      'bold',
      'italic',
      '|',
      // This is currently disabled because it creates an overlay on our overlay which isn't visible and shifts our window.
      //'link',
      //'|',
      'bulletedList',
      'numberedList',
      '|',
      'blockQuote',
    ],
    shouldNotGroupWhenFull: false,
  },
  plugins: [
    AutoLink,
    Autosave,
    BlockQuote,
    Bold,
    Essentials,
    GeneralHtmlSupport,
    Heading,
    Italic,
    Link,
    List,
    Paragraph,
    Markdown,
  ],
  heading: {
    options: [
      {
        model: 'paragraph',
        title: 'Paragraph',
        class: 'ck-heading_paragraph',
      },
      {
        model: 'heading1',
        view: 'h1',
        title: 'Heading 1',
        class: 'ck-heading_heading1',
      },
      {
        model: 'heading2',
        view: 'h2',
        title: 'Heading 2',
        class: 'ck-heading_heading2',
      },
      {
        model: 'heading3',
        view: 'h3',
        title: 'Heading 3',
        class: 'ck-heading_heading3',
      },
      {
        model: 'heading4',
        view: 'h4',
        title: 'Heading 4',
        class: 'ck-heading_heading4',
      },
      {
        model: 'heading5',
        view: 'h5',
        title: 'Heading 5',
        class: 'ck-heading_heading5',
      },
      {
        model: 'heading6',
        view: 'h6',
        title: 'Heading 6',
        class: 'ck-heading_heading6',
      },
    ],
  },
  htmlSupport: {
    allow: [
      {
        name: /^.*$/,
        styles: true,
        attributes: true,
        classes: true,
      },
    ],
  },
  licenseKey: 'GPL',
  link: {
    addTargetToExternalLinks: true,
    defaultProtocol: 'https://',
    decorators: {
      toggleDownloadable: {
        mode: 'manual',
        label: 'Downloadable',
        attributes: {
          download: 'file',
        },
      },
    },
  },
  placeholder: '',
  ui: {
    poweredBy: {
      forceVisible: false,
    },
  },
};

export default TextEditor;
