import _objectSpread from "@babel/runtime/helpers/objectSpread";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
// Copied from https://github.com/endaaman/markdown-react-js
import markdown from 'markdown-it'; // import React, { PropTypes } from 'react'

import React from 'react';
import PropTypes from 'prop-types';
import { style } from 'typestyle'; // import isPlainObject from 'lodash/isPlainObject'
// import assign from 'lodash/assign'
// import reduce from 'lodash/reduce'
// import zipObject from 'lodash/zipObject'
// import sortBy from 'lodash/sortBy'
// import compact from 'lodash/compact'
// import camelCase from 'lodash/camelCase'
// import isString from 'lodash/isString'
// import fromPairs from 'lodash/fromPairs'

import { isPlainObject, assign, reduce, zipObject, sortBy, compact, camelCase, isString, fromPairs } from 'lodash';
var DEFAULT_TAGS = {
  html: 'span'
};
var DEFAULT_RULES = {
  image: function image(token, attrs, children) {
    if (children.length) {
      attrs = assign({}, attrs, {
        alt: children[0]
      });
    }

    return [[token.tag, attrs]];
  },
  codeInline: function codeInline(token, attrs) {
    return [compact([token.tag, attrs, token.content])];
  },
  codeBlock: function codeBlock(token, attrs) {
    return [['pre', compact([token.tag, attrs, token.content])]];
  },
  fence: function fence(token, attrs) {
    if (token.info) {
      var langName = token.info.trim().split(/\s+/g)[0];
      attrs = assign({}, attrs, {
        'data-language': langName
      });
    }

    return [['pre', compact([token.tag, attrs, token.content])]];
  },
  hardbreak: function hardbreak() {
    return [['br']];
  },
  softbreak: function softbreak(token, attrs, children, options) {
    return options.breaks ? [['br']] : '\n';
  },
  text: function text(token) {
    return token.content;
  },
  htmlBlock: function htmlBlock(token) {
    return token.content;
  },
  htmlInline: function htmlInline(token) {
    return token.content;
  },
  inline: function inline(token, attrs, children) {
    return children;
  },
  default: function _default(token, attrs, children, options, getNext) {
    if (token.nesting === 1 && token.hidden) {
      return getNext();
    }
    /* plugin-related */


    if (!token.tag) {
      return token.content;
    }

    if (token.info) {
      attrs = assign({}, attrs, {
        'data-info': token.info.trim()
      });
    }
    /* plugin-related */


    return [compact([token.tag, attrs].concat(token.nesting === 1 && getNext()))];
  }
};

function convertTree(tokens, convertRules, options) {
  function convertBranch(tkns, nested) {
    var branch = [];

    if (!nested) {
      branch.push('html');
    }

    function getNext() {
      return convertBranch(tkns, true);
    }

    var token = tkns.shift();

    while (token && token.nesting !== -1) {
      var attrs = token.attrs && fromPairs(sortBy(token.attrs, 0));
      var children = token.children && convertBranch(token.children.slice(), true);
      var rule = convertRules[camelCase(token.type)] || convertRules.default;
      branch = branch.concat(rule(token, attrs, children, options, getNext));
      token = tkns.shift();
    }

    return branch;
  }

  return convertBranch(tokens, false);
}

function mdReactFactory() {
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

  var onIterate = options.onIterate,
      _options$tags = options.tags,
      tags = _options$tags === void 0 ? DEFAULT_TAGS : _options$tags,
      presetName = options.presetName,
      markdownOptions = options.markdownOptions,
      _options$enableRules = options.enableRules,
      enableRules = _options$enableRules === void 0 ? [] : _options$enableRules,
      _options$disableRules = options.disableRules,
      disableRules = _options$disableRules === void 0 ? [] : _options$disableRules,
      _options$plugins = options.plugins,
      plugins = _options$plugins === void 0 ? [] : _options$plugins,
      _options$onGenerateKe = options.onGenerateKey,
      onGenerateKey = _options$onGenerateKe === void 0 ? function (tag, index) {
    return "mdrct-".concat(tag, "-").concat(index);
  } : _options$onGenerateKe,
      rootElementProps = _objectWithoutProperties(options, ["onIterate", "tags", "presetName", "markdownOptions", "enableRules", "disableRules", "plugins", "onGenerateKey"]);

  var md = markdown(markdownOptions || presetName).enable(enableRules).disable(disableRules);
  var convertRules = assign({}, DEFAULT_RULES, options.convertRules);
  md = reduce(plugins, function (m, plugin) {
    return plugin.plugin ? m.use.apply(m, [plugin.plugin].concat(_toConsumableArray(plugin.args))) : m.use(plugin);
  }, md);

  function renderChildren(tag) {
    return ['img', 'hr', 'br'].indexOf(tag) < 0;
  }

  function iterateTree(tree) {
    var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
    var tag = tree.shift();
    var key = onGenerateKey(tag, index);
    var props = tree.length && isPlainObject(tree[0]) ? assign(tree.shift(), {
      key: key
    }) : {
      key: key
    };

    if (level === 0) {
      props = _objectSpread({}, props, rootElementProps);
    }

    var children = tree.map(function (branch, idx) {
      return Array.isArray(branch) ? iterateTree(branch, level + 1, idx) : branch;
    });
    tag = tags[tag] || tag;

    if (isString(props.style)) {
      props.style = zipObject(props.style.split(';').map(function (prop) {
        return prop.split(':');
      }).map(function (keyVal) {
        return [camelCase(keyVal[0].trim()), keyVal[1].trim()];
      }));
    }

    if (typeof onIterate === 'function') {
      var element = onIterate(tag, props, children, level);

      if (element) {
        return element;
      }
    }

    return React.createElement(tag, props, renderChildren(tag) ? children : undefined);
  }

  return function (text) {
    var tree = convertTree(md.parse(text, {}), convertRules, md.options);
    return iterateTree(tree);
  };
}

var MDReactComponent = function MDReactComponent(props) {
  var text = props.text,
      propsWithoutText = _objectWithoutProperties(props, ["text"]);

  return mdReactFactory(propsWithoutText)(text);
};

MDReactComponent.propTypes = {
  text: PropTypes.string.isRequired,
  onIterate: PropTypes.func,
  onGenerateKey: PropTypes.func,
  tags: PropTypes.object,
  presetName: PropTypes.string,
  markdownOptions: PropTypes.object,
  enableRules: PropTypes.array,
  disableRules: PropTypes.array,
  convertRules: PropTypes.object,
  plugins: PropTypes.array,
  className: PropTypes.string
};
export default MDReactComponent;
export { mdReactFactory as mdReact };