/* eslint-disable react/no-danger */
import { Component } from 'react';
import isEqual from 'lodash/isEqual';
function separateScripts(text) {
  if (!text) {
    return {
      inline: '',
      remotes: [],
      code: ''
    };
  }
  let inline = '';
  const scripts = text.match(/(<script.*src=.*?>.*<\/script>)/gim);
  const remotes = scripts ? scripts.map(script => script.match(/src=['"](.*)['"]/i)[1]) : [];
  const removedRemotes = text.replace(/(<script.*src=.*?>.*<\/script>)/gim, '');
  const code = removedRemotes.replace(/<script[^>]*>([\s\S]*?)<\/script>/gim, (match, group) => {
    inline += `${group}\n`;
    return '';
  });
  return {
    inline,
    remotes,
    code
  };
}
function injectInlineScript(script) {
  const body = window.document.getElementsByTagName('body')[0];
  const scriptElement = window.document.createElement('script');
  scriptElement.setAttribute('type', 'text/javascript');
  scriptElement.innerHTML = script;
  body.appendChild(scriptElement);
  body.removeChild(scriptElement);
}
function injectRemoteScript(src) {
  if (window.document.querySelector(`script[src="${src}"]`)) return;
  const body = window.document.getElementsByTagName('body')[0];
  const scriptElement = window.document.createElement('script');
  scriptElement.setAttribute('src', src);
  body.appendChild(scriptElement);
}
class Code extends Component {
  componentDidMount() {
    const {
      props
    } = this;
    const {
      inline,
      remotes
    } = separateScripts(props.code);
    injectInlineScript(inline);
    remotes.forEach(src => injectRemoteScript(src));
  }
  componentDidUpdate(prevProps) {
    const newProps = this.props;
    const {
      inline: prevInline,
      remotes: prevRemotes
    } = separateScripts(prevProps.code);
    const {
      inline,
      remotes
    } = separateScripts(newProps.code);
    if (!isEqual(prevRemotes.sort(), remotes.sort())) {
      remotes.forEach(src => injectRemoteScript(src));
    }
    if (prevInline !== inline || prevProps.active !== newProps.active) {
      injectInlineScript(inline);
    }
  }
  render() {
    const {
      active,
      code: combinedCode,
      className
    } = this.props;
    const {
      code
    } = separateScripts(combinedCode);
    if (!active) {
      return null;
    }
    return <div className={className} dangerouslySetInnerHTML={{
      __html: code
    }} />;
  }
}
export default Code;