import { inject, injectable } from "inversify";
import * as React from "react";
import { ReactElement } from "react";
import { render } from "react-dom";
import { renderToStaticMarkup } from "react-dom/server";
import {
  IRenderer,
  IRenderOptions,
  IRequire,
} from "../interfaces";
import TYPES from "../types";

@injectable()
export default class Renderer implements IRenderer {
  private loader: IRequire;
  private _render;
  private _renderToString;

  constructor(
    @inject(TYPES.IRequire) loader: IRequire,
    @inject(TYPES.render) render,
    @inject(TYPES.renderToString) renderToString,
  ) {
    this.loader = loader;
    this._render = render;
    this._renderToString = renderToString;
  }

  public render({ component, props = {}, el }: IRenderOptions) {
    const Component = this.loadComponent(component);

    const instance = <Component {...props} />;
    const html = this._renderToString(instance);

    if (!el) {
      return renderToStaticMarkup(
        <div
          data-lpui-component={component}
          data-lpui-component-props={JSON.stringify(props)}
          dangerouslySetInnerHTML={{ __html: html }}
        />,
      );
    }

    return this._render(instance, el);
  }

  private loadComponent(name: string): any {
    return this.loader(name);
  }
}
