/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
import CopyToClipboard from 'react-copy-to-clipboard';
import classNames from 'classnames';
import LZString from 'lz-string';
import {Icon, Tooltip} from 'antd';
import EditButton from './EditButton';
import ErrorBoundary from './ErrorBoundary';
import BrowserFrame from '../BrowserFrame';
import {ping} from '../utils';

function compress(string) {
  return LZString.compressToBase64(string)
    .replace(/\+/g, '-') // Convert '+' to '-'
    .replace(/\//g, '_') // Convert '/' to '_'
    .replace(/=+$/, ''); // Remove ending '='
}


const CODE_EXPAND_ICON = {
  dark: '#A4A5B3',
  green: '#22bae0',
  default: '#000000'
};

export default class Demo extends React.Component {
  iframeRef = React.createRef();

  static contextTypes = {
    intl: PropTypes.object
  };

  state = {
    codeExpand: false,
    copied: false,
    copyTooltipVisible: false,
    showRiddleButton: false
  };

  componentDidMount() {
    const {meta, location} = this.props;
    if (meta.id === location.hash.slice(1)) {
      this.anchor.click();
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const {codeExpand, copied, copyTooltipVisible} = this.state;
    const {expand, theme} = this.props;
    return (
      (codeExpand || expand) !== (nextState.codeExpand || nextProps.expand)
      || copied !== nextState.copied
      || copyTooltipVisible !== nextState.copyTooltipVisible
        || theme !== nextProps.theme
    );
  }

  getSourceCode() {
    const {highlightedCode} = this.props;
    if (typeof document !== 'undefined') {
      const div = document.createElement('div');
      div.innerHTML = highlightedCode[1].highlighted;
      return div.textContent;
    }
    return '';
  }

  handleCodeExpand = () => {
    const {codeExpand} = this.state;
    this.setState({codeExpand: !codeExpand});
  };

  saveAnchor = (anchor) => {
    this.anchor = anchor;
  };

  handleCodeCopied = () => {
    this.setState({copied: true});
  };

  onCopyTooltipVisibleChange = (visible) => {
    if (visible) {
      this.setState({
        copyTooltipVisible: visible,
        copied: false
      });
      return;
    }
    this.setState({
      copyTooltipVisible: visible
    });
  };

  handleIframeReady = () => {
    const {theme, setIframeTheme} = this.props;
    if (this.iframeRef.current) {
      setIframeTheme(this.iframeRef.current, theme);
    }
  };

  render() {
    const {state} = this;
    const {props} = this;
    const {meta, src, content, preview, highlightedCode, style, highlightedStyle, expand, theme} = props;
    const {showRiddleButton, copied} = state;
    if (!this.liveDemo) {
      this.liveDemo = meta.iframe ? (
        <BrowserFrame>
          <iframe
            ref={this.iframeRef}
            onLoad={this.handleIframeReady}
            src={src}
            height={meta.iframe}
            title='demo'
            className='iframe-demo'
          />
        </BrowserFrame>
      ) : (
        preview(React, ReactDOM)
      );
    }
    const codeExpand = state.codeExpand || expand;
    const codeBoxClass = classNames({
      'code-box': true,
      expand: codeExpand
    });
    const {
      intl: {locale}
    } = this.context;
    const localizedTitle = meta.title[locale] || meta.title;
    const localizeIntro = content[locale] || content;
    const introChildren = props.utils.toReactComponent(['div'].concat(localizeIntro));

    const highlightClass = classNames({
      'highlight-wrapper': true,
      'highlight-wrapper-expand': codeExpand
    });

    const prefillStyle = `@import 'antd/dist/antd.css';\n\n${style || ''}`.replace(
      new RegExp(`#${meta.id}\\s*`, 'g'),
      ''
    );
    const html = `<div id="container" style="padding: 24px"></div>
<script>
  var mountNode = document.getElementById('container');
</script>`;

    const sourceCode = this.getSourceCode();

    const codepenPrefillConfig = {
      title: `${localizedTitle} - Ant Design Demo`,
      html,
      js: sourceCode
        .replace(/import\s+\{\s+(.*)\s+\}\s+from\s+'antd';/, 'const { $1 } = antd;')
        .replace("import moment from 'moment';", '')
        .replace(/import\s+\{\s+(.*)\s+\}\s+from\s+'react-router';/, 'const { $1 } = ReactRouter;')
        .replace(
          /import\s+\{\s+(.*)\s+\}\s+from\s+'react-router-dom';/,
          'const { $1 } = ReactRouterDOM;'
        )
        .replace(/([a-zA-Z]*)\s+as\s+([a-zA-Z]*)/, '$1:$2'),
      css: prefillStyle,
      editors: '001',
      css_external: 'https://unpkg.com/antd/dist/antd.css',
      js_external: [
        'react@16.x/umd/react.development.js',
        'react-dom@16.x/umd/react-dom.development.js',
        'moment/min/moment-with-locales.js',
        'antd/dist/antd-with-locales.js',
        'react-router-dom/umd/react-router-dom.min.js',
        'react-router@3.x/umd/ReactRouter.min.js'
      ]
        .map(url => `https://unpkg.com/${url}`)
        .join(';'),
      js_pre_processor: 'typescript'
    };
    const riddlePrefillConfig = {
      title: `${localizedTitle} - Ant Design Demo`,
      js: sourceCode,
      css: prefillStyle
    };
    const dependencies = sourceCode.split('\n').reduce(
      (acc, line) => {
        const matches = line.match(/import .+? from '(.+)';$/);
        if (matches && matches[1] && !line.includes('antd')) {
          acc[matches[1]] = 'latest';
        }
        return acc;
      },
      {react: 'latest', 'react-dom': 'latest', antd: 'latest'}
    );
    const codesanboxPrefillConfig = {
      files: {
        'package.json': {
          content: {
            dependencies
          }
        },
        'index.css': {
          content: (style || '').replace(new RegExp(`#${meta.id}\\s*`, 'g'), '')
        },
        'index.js': {
          content: `
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
${sourceCode.replace('mountNode', "document.getElementById('container')")}
          `
        },
        'index.html': {
          content: html
        }
      }
    };
    return (
      <section className={codeBoxClass} id={meta.id}>
        <section className='code-box-demo'>
          <ErrorBoundary>{this.liveDemo}</ErrorBoundary>
          {style ? (
            <style dangerouslySetInnerHTML={{ __html: style }} /> // eslint-disable-line
          ) : null}
        </section>
        <section className='code-box-meta markdown'>
          <div className='code-box-title'>
            <a href={`#${meta.id}`} ref={this.saveAnchor}>
              {localizedTitle}
            </a>
          </div>
          {introChildren}
          <Tooltip title={codeExpand ? 'Hide Code' : 'Show Code'}>
            <span className='code-expand-icon'>
              <span
                className={codeExpand ? 'code-expand-icon-hide' : 'code-expand-icon-show'}
                onClick={this.handleCodeExpand}
              >
                <svg width='1024px' height='1024px' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg'>
                  <g id='小站' stroke='none' strokeWidth='1' fill='none' fillRule='evenodd' opacity='0.779734142'>
                    <g id='code' fill={CODE_EXPAND_ICON[theme]}>
                      <path d='M1018.64495,531.297637 C1027.27952,512.687401 1023.24618,489.87879 1007.20328,475.433694 L802.095304,290.753647 L802.095304,290.753647 C782.394782,273.015217 752.044514,274.605807 734.306083,294.306329 L734.306083,294.306329 L734.306083,294.306329 C716.567653,314.006852 718.158243,344.35712 737.858766,362.09555 L904.138417,511.81442 L736.858766,662.433694 C717.158243,680.172125 715.567653,710.522392 733.306083,730.222915 C751.044514,749.923438 781.394782,751.514028 801.095304,733.775598 L1006.20328,549.09555 C1011.84552,544.015251 1016.00229,537.90046 1018.64495,531.297643 Z M119.947,511.390231 L286.22665,361.671361 C305.927173,343.932931 307.517763,313.582663 289.779333,293.88214 L289.779333,293.88214 L289.779333,293.88214 C272.040903,274.181618 241.690635,272.591027 221.990112,290.329458 L221.990112,290.329458 L16.8821402,475.009505 C0.839236202,489.454601 -3.19410198,512.263212 5.44046645,530.873448 C8.08312579,537.476271 12.2398959,543.591061 17.8821402,548.671361 L222.990112,733.351408 C242.690635,751.089839 273.040903,749.499248 290.779333,729.798726 C308.517763,710.098203 306.927173,679.747935 287.22665,662.009505 L119.947,511.390231 Z' id='Combined-Shape' />
                    </g>
                  </g>
                </svg>
              </span>
              <span
                className={codeExpand ? 'code-expand-icon-show' : 'code-expand-icon-hide'}
                onClick={this.handleCodeExpand}
              >
                <svg width='1024px' height='1024px' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg'>
                  <g id='小站' stroke='none' strokeWidth='1' fill='none' fillRule='evenodd' opacity='0.779734142'>
                    <g id='code-open' fill={CODE_EXPAND_ICON[theme]}>
                      <path d='M1018.64495,531.297637 C1027.27952,512.687401 1023.24618,489.87879 1007.20328,475.433694 L802.095304,290.753647 C782.394782,273.015217 752.044514,274.605807 734.306083,294.306329 C716.567653,314.006852 718.158243,344.35712 737.858766,362.09555 L904.138417,511.81442 L736.858766,662.433694 C717.158243,680.172125 715.567653,710.522392 733.306083,730.222915 C751.044514,749.923438 781.394782,751.514028 801.095304,733.775598 L1006.20328,549.09555 C1011.84552,544.015251 1016.00229,537.90046 1018.64495,531.297643 Z M119.947,511.390231 L286.22665,361.671361 C305.927173,343.932931 307.517763,313.582663 289.779333,293.88214 C272.040903,274.181618 241.690635,272.591027 221.990112,290.329458 L16.8821402,475.009505 C0.839236202,489.454601 -3.19410198,512.263212 5.44046645,530.873448 C8.08312579,537.476271 12.2398959,543.591061 17.8821402,548.671361 L222.990112,733.351408 C242.690635,751.089839 273.040903,749.499248 290.779333,729.798726 C308.517763,710.098203 306.927173,679.747935 287.22665,662.009505 L119.947,511.390231 Z M649.492098,134.243566 C674.403037,143.310407 687.247217,170.85484 678.180377,195.765779 L436.030115,861.068155 C426.963275,885.979094 399.418842,898.823274 374.507902,889.756434 C349.596963,880.689593 336.752783,853.14516 345.819623,828.234221 L587.969885,162.931845 L587.969885,162.931845 C597.036725,138.020906 624.581158,125.176726 649.492098,134.243566 Z' id='Combined-Shape' />
                    </g>
                  </g>
                </svg>
              </span>
              {/* <img
                alt='expand code'
                src={theme === 'dark' ? '/images/showCodeDark.svg' : '/images/showCode.svg'}
                className={codeExpand ? 'code-expand-icon-hide' : 'code-expand-icon-show'}
                onClick={this.handleCodeExpand}
              />
              <img
                alt='expand code'
                src={theme === 'dark' ? '/images/hideCodeDark.svg' : '/images/hideCode.svg'}
                className={codeExpand ? 'code-expand-icon-show' : 'code-expand-icon-hide'}
                onClick={this.handleCodeExpand}
              /> */}
            </span>
          </Tooltip>
        </section>
        <section className={highlightClass} key='code'>
          <div className='highlight'>
            <div className='code-box-actions'>
              {showRiddleButton ? (
                <form
                  action='//riddle.alibaba-inc.com/riddles/define'
                  method='POST'
                  target='_blank'
                >
                  <input type='hidden' name='data' value={JSON.stringify(riddlePrefillConfig)} />
                  <Tooltip title={<FormattedMessage id='app.demo.riddle' />}>
                    <input
                      type='submit'
                      value='Create New Riddle with Prefilled Data'
                      className='code-box-riddle'
                    />
                  </Tooltip>
                </form>
              ) : null}
              <CopyToClipboard text={sourceCode} onCopy={this.handleCodeCopied}>
                <Tooltip
                  visible={state.copyTooltipVisible}
                  onVisibleChange={this.onCopyTooltipVisibleChange}
                  title={<FormattedMessage id={`app.demo.${copied ? 'copied' : 'copy'}`} />}
                >
                  <Icon
                    type={state.copied && state.copyTooltipVisible ? 'check' : 'copy'}
                    className='code-box-code-copy'
                  />
                </Tooltip>
              </CopyToClipboard>
            </div>
            {props.utils.toReactComponent(highlightedCode)}
          </div>
          {highlightedStyle ? (
            <div key='style' className='highlight'>
              <pre>
                <code className='css' dangerouslySetInnerHTML={{__html: highlightedStyle}} />
                {' '}
                {/* eslint-disable-line */}
              </pre>
            </div>
          ) : null}
        </section>
      </section>
    );
  }
}
