import { useEffect, useState, createElement } from '__RAX_OR_REACT__';
import PropTypes from 'prop-types';
import { convertTheme2Css, addStyle } from '../../common/utils';
import { normalizeSchema } from './utils';
import cssVariablesExtract from '../../common/css-variables-extract';
import { $on, $off, $emit } from '../../common/event';
import Page from './Page';

import './index.scss';

function appendStyle(root, theme) {
  const styleSheets = document.querySelector('#style').content.cloneNode(true);
  const styleEl = document.createElement('style');

  Array.prototype.forEach.call(
    styleSheets.children,
    el => (styleEl.textContent += el.textContent + '\n')
  );
  root.appendChild(styleEl);

  // 需要在外部样式中加上字体样式，shadow中声明的字体样式不会生效
  const [fontFamily, fontPath] = ['--icon-font-family', '--icon-font-path'].map(
    name => (theme.find(v => v.name === name) || '').value
  );

  if (fontFamily && fontPath) {
    let fotnEl = document.querySelector('#font-face-style');
    if (!fotnEl) {
      fotnEl = document.createElement('style');
      fotnEl.id = 'font-face-style';
    }

    const fontSrc = fontPath.match('format')
      ? fontPath
      : `${fontPath} format('truetype')`;

    fotnEl.textContent = `
      @font-face {
        font-family: ${fontFamily};
        src: ${fontSrc};
      }`;
    document.head.appendChild(fotnEl);
  }
}

export default function ConfigView(props) {
  let viewEl = null;
  let preTarget = null;
  let scale = 1;
  const [theme, setTheme] = useState(props.theme);

  const handleChange = (__, v) => setTheme(v);

  useEffect(() => {
    const root = props.root || viewEl;
    const current = root.shadowRoot || root;

    appendStyle(current, theme);

    // 监听ConfigItem的配置事件
    function handleSelect(e) {
      const target = e.type === 'reconfig' ? preTarget : e.target;

      preTarget && preTarget.classList.remove('active');
      target.classList.add('active');
      preTarget = target;

      // 触发该事件的时候，组件可能还没完成重新渲染
      // 所以加了setTimeout
      setTimeout(() => {
        console.time('cssVariablesExtract');
        const variables = cssVariablesExtract(target.children, current);
        console.timeEnd('cssVariablesExtract');
        $emit(root, 'config', variables);
      });
      e.stopPropagation();
    }

    function handleWheel(e) {
      if (e.ctrlKey) {
        scale -= e.deltaY * 0.01;
        e.preventDefault();
      }
      if (scale > 1) {
        scale = 1;
      } else if (scale < 0.25) {
        scale = 0.25;
      }

      current.querySelector('.config-view').style.transform =
        'scale(' + scale + ')';
    }

    $on(current, 'select', handleSelect);
    $on(current, 'themechange', handleChange, true);
    $on(current, 'reconfig', handleSelect);
    $on(document, 'wheel', handleWheel, { passive: false });

    // 初始化 默认选中第一个
    const firstItem = current.querySelector('.config-item');
    firstItem && $emit(firstItem, 'click');

    return () => {
      $off(current, 'select', handleSelect);
      $off(current, 'themechange', handleChange, true);
      $off(current, 'reconfig', handleSelect);
      // $off(document, 'wheel', handleWheel, { passive: false });
    };
  }, []);

  useEffect(() => {
    const root = props.root || viewEl;
    const current = root.shadowRoot || root;
    addStyle(convertTheme2Css(theme), current, 'root-style');
  });

  return (
    <div className='config-view' ref={el => (viewEl = el)}>
      {normalizeSchema(props.schema).map((schema, index) => (
        <Page key={index} {...schema} theme={theme} />
      ))}
    </div>
  );
}

ConfigView.propTypes = {
  children: PropTypes.node,
  schema: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.arrayOf(PropTypes.object),
  ]),
  root: PropTypes.object,
  theme: PropTypes.arrayOf(PropTypes.object),
};
