import { createRoot } from 'react-dom/client';
import { App, AppProps } from './App';
import React from 'react';

export class ReactRenderer {
  component: any;
  element: HTMLElement;
  ref: React.RefObject<any>;
  props: any;
  root: any;
  constructor(component: any, { props, className }: any) {
    this.component = component;
    const el = document.createElement('div');
    this.element = el;
    this.ref = React.createRef();
    this.props = {
      ...props,
      ref: this.ref,
    };
    el.className = className;
    this.root = createRoot(this.element);
    this.render();
  }

  updateProps(props: any) {
    this.props = {
      ...this.props,
      ...props,
    };
    this.render();
  }

  render() {
    this.root.render(React.createElement(this.component, this.props));
  }

  destroy() {
    this.root.unmount();
  }
}

export default ReactRenderer;
export const randomId = () => {
  return Math.random().toString(36).substring(2, 15);
};
export const render = (el: HTMLElement | string, props?: AppProps) => {
  const root = typeof el === 'string' ? document.querySelector(el) : el;
  if (!root) {
    console.error('root not found');
    return;
  }
  const hasResourceApp = window.context?.codemirrorApp;
  if (hasResourceApp) {
    const render = hasResourceApp as ReactRenderer;
    render.updateProps({
      props: { t: randomId(), ...props },
    });
    root.innerHTML = '';
    root.appendChild(render.element);
  } else {
    const renderer = new ReactRenderer(App, {
      props: { ...props },
      className: 'codemirror-root w-full h-full',
    });
    if (window.context) {
      window.context.codemirrorApp = renderer;
    } else {
      window.context = {
        codemirrorApp: renderer,
      };
    }
    root.appendChild(renderer.element);
  }
};

export const unmount = (el: HTMLElement | string) => {
  const root = typeof el === 'string' ? document.querySelector(el) : el;
  if (!root) {
    console.error('root not found');
    return;
  }
  const hasResourceApp = window.context?.codemirrorApp;
  if (hasResourceApp) {
    const render = hasResourceApp as ReactRenderer;
    render.destroy();
    window.context.codemirrorApp = null;
  }
};
