/*-
 * #%L
 * Markdown Editor Add-on
 * %%
 * Copyright (C) 2024 Flowing Code
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
import {type ReactElement} from 'react';
import {
  useState,
  useRef,
  Fragment,
  useEffect,
  useCallback
} from "react";
import ReactDOM from "react-dom";
import MDEditor from '@uiw/react-md-editor/nohighlight';
import {ReactAdapterElement, type RenderHooks} from "Frontend/generated/flow/ReactAdapter";
import React from 'react';
import "@uiw/react-md-editor/markdown-editor.css";
import "@uiw/react-markdown-preview/markdown.css";
import rehypeSanitize from "rehype-sanitize";
import mermaid from "mermaid";
import { getCodeString } from "rehype-rewrite";

mermaid.initialize({
  suppressErrorRendering: true,
});

const randomid = () => parseInt(String(Math.random() * 1e15), 10).toString(36);
const Code = ({ inline, children = [], className, ...props }) => {
  const demoid = useRef(`dome${randomid()}`);
  const [container, setContainer] = useState(null);
  const isMermaid =
    className && /^language-mermaid/.test(className.toLocaleLowerCase());
  const code = children
    ? getCodeString(props.node.children)
    : children[0] || "";

  useEffect(() => {
    if (container && isMermaid && demoid.current && code) {
      mermaid
        .render(demoid.current, code)
        .then(({ svg, bindFunctions }) => {
          container.innerHTML = svg;
          if (bindFunctions) {
            bindFunctions(container);
          }
        })
        .catch((error) => {
          console.log("error:", error);
        });
    }
  }, [container, isMermaid, code, demoid]);

  const refElement = useCallback((node) => {
    if (node !== null) {
      setContainer(node);
    }
  }, []);

  if (isMermaid) {
    return (
      <Fragment>
        <code id={demoid.current} style={{ display: "none" }} />
        <code className={className} ref={refElement} data-name="mermaid" />
      </Fragment>
    );
  }
  return <code className={className}>{children}</code>;
};

class MarkdownEditorElement extends ReactAdapterElement {

    protected override render(hooks: RenderHooks): ReactElement | null {
      const [content, setContent] = hooks.useState<string>("content"); 
      const [placeholder] = hooks.useState<string>("placeholder");
      const [maxLength] = hooks.useState<number>("maxLength");
      
      return <MDEditor visibleDragbar={false} 
                        value={content} 
                        onChange={setContent} 
                        textareaProps={{
                          placeholder: placeholder,
                          maxLength: maxLength
                        }}
                        previewOptions={{
                              rehypePlugins: [[rehypeSanitize]],
                              components: {
                                  code: Code
                                }
                            }}
                        />;
    }
}
  
customElements.define("markdown-editor",MarkdownEditorElement);
