content: import React, { Component } from 'react';
  import PropTypes from 'prop-types';
  import { CodeSnippet } from 'components/test';
  import isString from 'lodash/isString';
  import classNames from 'classnames/bind';
  import styles from './test.css';
  
  const cx = classNames.bind(styles);
  
  const videoRegEx = /(mp4|webm)$/i;
  const imgRegEx = /(?:png|jpe?g|gif)$/i;
  const protocolRegEx = /^(?:(?:https?|ftp):\/\/)/i;
  const urlRegEx = /^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/; // eslint-disable-line
  const base64ImgRegEx = /^data:image\/([a-zA-Z0-9-_.])+;base64,([^"]*)$/i;
  const base64VidRegEx = /^data:video\/(mp4|webm);base64,(?:[^"]*)$/i;
  
  const getVideoType = str => {
    if (!isString(str)) {
      return undefined;
    }
  
    const hashIndex = str.indexOf('#');
  
    const [, type] =
      videoRegEx.exec(hashIndex > 0 ? str.slice(0, hashIndex) : str) ||
      base64VidRegEx.exec(str) ||
      [];
    return type || undefined;
  };
  
  class TestContext extends Component {
    static displayName = 'TestContext';
  
    static propTypes = {
      className: PropTypes.string,
      context: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.object,
        PropTypes.array,
      ]),
    };
  
    renderVideo = (ctx, title, type) => {
      const isUrl = urlRegEx.test(ctx);
      const hasProtocol = protocolRegEx.test(ctx);
      const linkUrl = isUrl && !hasProtocol ? `http://${ctx}` : ctx;
  
      return (
        <video controls className={cx('video')}>
          <source type={`video/${type}`} src={linkUrl} />
          <track kind="captions" />
          {title}
          {isUrl && (
            <a
              href={linkUrl}
              className={cx('video-link')}
              rel="noopener noreferrer"
              target="_blank">
              {linkUrl}
            </a>
          )}
        </video>
      );
    };
  
    renderImage = (ctx, title) => {
      const isUrl = urlRegEx.test(ctx);
      const hasProtocol = protocolRegEx.test(ctx);
      const linkUrl = isUrl && !hasProtocol ? `http://${ctx}` : ctx;
      return (
        <a
          href={linkUrl}
          className={cx('image-link')}
          rel="noopener noreferrer"
          target="_blank">
          <img src={linkUrl} className={cx('image')} alt={title} />
        </a>
      );
    };
  
    renderBase64Image = (ctx, title) => (
      <img src={ctx} className={cx('image')} alt={title} />
    );
  
    renderLink = (url, title) => {
      const linkUrl = `${protocolRegEx.test(url) ? '' : 'http://'}${url}`;
      return (
        <a
          href={linkUrl}
          className={cx('text-link')}
          rel="noopener noreferrer"
          target="_blank"
          alt={title}>
          {url}
        </a>
      );
    };
  
    renderContextContent = (content, title, highlight = false) => {
      // Videos
      const videoType = getVideoType(content);
      if (videoType) {
        return this.renderVideo(content, title, videoType);
      }
  
      // Images
      if (imgRegEx.test(content)) {
        return this.renderImage(content, title);
      }
  
      // Base64 Images
      if (base64ImgRegEx.test(content)) {
        return this.renderBase64Image(content, title);
      }
  
      // URLs
      if (urlRegEx.test(content)) {
        return this.renderLink(content, title);
      }
  
      // Simple string
      if (isString(content)) {
        return (
          <CodeSnippet
            className={cx('code-snippet')}
            code={content}
            highlight={false}
          />
        );
      }
  
      // All other types (primitives, objects, arrays...)
      const code = JSON.stringify(content, null, 2);
      return (
        <CodeSnippet
          className={cx('code-snippet')}
          code={code}
          highlight={highlight}
        />
      );
    };
  
    renderContext = (ctx, i) => {
      const containerProps = {
        className: cx('context-item'),
      };
      if (i !== undefined) {
        containerProps.key = i;
      }
  
      // Context is a simple string
      if (isString(ctx)) {
        return <div {...containerProps}>{this.renderContextContent(ctx)}</div>;
      }
  
      // Context is an object with title and value
      const { title, value } = ctx;
      return (
        <div {...containerProps}>
          <h4 className={cx('context-item-title')}>{title}:</h4>
          {this.renderContextContent(value, title, true)}
        </div>
      );
    };
  
    render() {
      const { className, context } = this.props;
  
      // All context comes in stringified initially so we parse it here
      const ctx = JSON.parse(context);
      return (
        <div className={cx(className, 'context')}>
          <h4 className={cx('context-title')}>Additional Test Context</h4>
          {Array.isArray(ctx)
            ? ctx.map(this.renderContext)
            : this.renderContext(ctx)}
        </div>
      );
    }
  }
  
  export default TestContext;
  