"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.transformUnorderedList = exports.transformTableRow = exports.transformTableCell = exports.transformTable = exports.transformParagraph = exports.transformOrderedList = exports.transformMath = exports.transformListItem = exports.transformListContent = exports.transformList = exports.transformHtml = exports.transformHr = exports.transformHeader = exports.transformDefinition = exports.transformCodeLine = exports.transformCodeBlock = exports.transformCheckListItem = exports.transformCheckList = exports.transformBlockquote = exports.transformBlockHtml = exports.formatMdToSlate = void 0;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
var _slugid = _interopRequireDefault(require("slugid"));
var _core = require("../../extension/core");
var _elementTypes = require("../../extension/constants/element-types");
var _htmlToSlate = _interopRequireDefault(require("../html-to-slate"));
const INLINE_KEY_MAP = {
  strong: 'bold',
  emphasis: 'italic'
};

// <strong><em>aa<em>bb<em></strong>
const applyMarkForInlineItem = function (result, item) {
  let textNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  const {
    type,
    children,
    value
  } = item;
  if (type === _elementTypes.LINK) {
    const child = children.length === 0 ? {
      type: 'text',
      value: ''
    } : children[0];
    const linkChildren = [{
      id: _slugid.default.nice(),
      text: child.value || ''
    }];
    const link = {
      id: _slugid.default.nice(),
      type: _elementTypes.LINK,
      url: item.url,
      title: item.title,
      children: linkChildren
    };
    result.push([(0, _core.generateDefaultText)(), link, (0, _core.generateDefaultText)()]);
    return result;
  }
  if (type === _elementTypes.IMAGE) {
    const data = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({
      src: item.url
    }, item.title && {
      title: item.title
    }), item.alt && {
      alt: item.alt
    }), item.width && {
      width: item.width
    }), item.height && {
      height: item.height
    });
    const image = {
      id: _slugid.default.nice(),
      data: data,
      type: _elementTypes.IMAGE,
      children: [(0, _core.generateDefaultText)()]
    };
    result.push([(0, _core.generateDefaultText)(), image, (0, _core.generateDefaultText)()]);
    return result;
  }

  // Handle special images
  if (type === 'html') {
    const nodes = transformHtml(item);
    result.push(nodes);
    return result;
  }
  if (!textNode.id) {
    textNode['id'] = _slugid.default.nice();
  }
  if (type === 'text') {
    // https://symbl.cc/en/200B/
    const formatValue = value && value !== '​' ? value : '';
    textNode['text'] = formatValue;
    result.push((0, _objectSpread2.default)({}, textNode));

    // reset testNode
    textNode = {};
    return;
  }
  if (type === 'inlineCode') {
    textNode['code'] = true;
    textNode['text'] = value || '';
    result.push((0, _objectSpread2.default)({}, textNode));

    // reset testNode
    textNode = {};
    return;
  }
  if (type === 'linkReference') {
    var _item$children$;
    textNode['type'] = _elementTypes.LINK_REFERENCE;
    textNode['identifier'] = item.identifier;
    textNode['referenceType'] = item.referenceType;
    textNode['label'] = (_item$children$ = item.children[0]) === null || _item$children$ === void 0 ? void 0 : _item$children$.value;
    textNode['children'] = [{
      id: _slugid.default.nice(),
      text: ''
    }];
    result.push((0, _objectSpread2.default)({}, textNode));

    // reset testNode
    textNode = {};
    return;
  }
  const attr_key = INLINE_KEY_MAP[type];
  if (!Array.isArray(children) || children.length === 0 || !attr_key) {
    textNode['text'] = value || '';
    result.push((0, _objectSpread2.default)({}, textNode));

    // reset testNode
    textNode = {};
    return;
  }
  textNode[attr_key] = true;
  children.forEach(item => {
    applyMarkForInlineItem(result, item, (0, _objectSpread2.default)({}, textNode));
  });
};
const transformNodeWithInlineChildren = node => {
  const {
    children
  } = node;
  const defaultChildren = [(0, _core.generateDefaultText)()];
  if (!children || !Array.isArray(children) || children.length === 0) {
    return defaultChildren;
  }
  const result = [];
  children.forEach(item => applyMarkForInlineItem(result, item));
  return result.flat();
};
const transformHeader = node => {
  const {
    depth
  } = node;
  const type = "".concat(_elementTypes.HEADER).concat(depth);
  return {
    id: _slugid.default.nice(),
    type: type,
    children: transformNodeWithInlineChildren(node)
  };
};
exports.transformHeader = transformHeader;
const transformParagraph = node => {
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.PARAGRAPH,
    children: transformNodeWithInlineChildren(node)
  };
};
exports.transformParagraph = transformParagraph;
const transformBlockquote = node => {
  const {
    children
  } = node;
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.BLOCKQUOTE,
    children: Array.isArray(children) && children.length > 0 ? children.map(child => {
      const handler = elementHandlers[child.type];
      return handler(child); // flat
    }).flat() : [{
      id: _slugid.default.nice(),
      type: _elementTypes.PARAGRAPH,
      children: [{
        id: _slugid.default.nice(),
        text: ''
      }]
    }]
  };
};
exports.transformBlockquote = transformBlockquote;
const transformListContent = node => {
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.PARAGRAPH,
    children: transformNodeWithInlineChildren(node)
  };
};
exports.transformListContent = transformListContent;
const transformListItem = node => {
  const {
    children
  } = node;
  if (children.length === 0) {
    return {
      id: _slugid.default.nice(),
      type: _elementTypes.LIST_ITEM,
      // eslint-disable-next-line array-callback-return
      children: [transformListContent({})]
    };
  }
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.LIST_ITEM,
    // eslint-disable-next-line array-callback-return
    children: children.map(child => {
      if (child.type === _elementTypes.PARAGRAPH) {
        return transformListContent(child);
      } else if (child.type === 'code') {
        return transformCodeBlock(child);
      } else if (child.type === 'blockquote') {
        return transformBlockquote(child);
      } else if (child.type === 'list') {
        const hasParent = true;
        return transformList(child, hasParent);
      } else if (child.type === 'heading') {
        return transformParagraph(child);
      } else if (child.type === 'html') {
        // patch
        return transformBlockHtml(child);
      } else if (child.type === 'thematicBreak') {
        // patch
        return transformParagraph(child);
      } else {
        console.warn('Unhandled child type in list item:', child);
        return (0, _core.generateDefaultParagraph)();
      }
    }).flat()
  };
};
exports.transformListItem = transformListItem;
const transformOrderedList = node => {
  const {
    children
  } = node;
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.ORDERED_LIST,
    children: children.map(child => transformListItem(child))
  };
};
exports.transformOrderedList = transformOrderedList;
const transformUnorderedList = node => {
  const {
    children
  } = node;
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.UNORDERED_LIST,
    children: children.map(child => transformListItem(child))
  };
};
exports.transformUnorderedList = transformUnorderedList;
const transformCheckListItem = node => {
  const {
    children,
    checked
  } = node;
  if (children.length === 0) {
    return {
      id: _slugid.default.nice(),
      type: _elementTypes.CHECK_LIST_ITEM,
      checked: checked ? true : false,
      children: transformNodeWithInlineChildren({})
    };
  }
  if (children.length === 1) {
    return {
      id: _slugid.default.nice(),
      type: _elementTypes.CHECK_LIST_ITEM,
      checked: checked ? true : false,
      children: children.map(child => transformNodeWithInlineChildren(child)).flat()
    };
  }
  const [child, ...reset] = children;
  const firstChild = {
    id: _slugid.default.nice(),
    type: _elementTypes.CHECK_LIST_ITEM,
    checked: checked,
    children: transformNodeWithInlineChildren(child)
  };
  const resetChildren = formatMdToSlate(reset);
  return [firstChild, ...resetChildren];
};
exports.transformCheckListItem = transformCheckListItem;
const transformCheckList = node => {
  const {
    children
  } = node;
  return children.map(child => transformCheckListItem(child)).flat();
};
exports.transformCheckList = transformCheckList;
const transformList = (node, hasParent) => {
  const {
    ordered,
    children
  } = node;
  const firstChild = children[0];
  if (ordered === true) {
    return transformOrderedList(node);
  }
  if (ordered === false && firstChild.checked === null) {
    return transformUnorderedList(node);
  }
  // patch tasklist in list
  if (hasParent) {
    return transformUnorderedList(node);
  }
  return transformCheckList(node);
};
exports.transformList = transformList;
const transformTableCell = (cell, align) => {
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.TABLE_CELL,
    children: transformNodeWithInlineChildren(cell)
  };
};
exports.transformTableCell = transformTableCell;
const transformTableRow = row => {
  const {
    children: cells
  } = row;
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.TABLE_ROW,
    children: cells.map(cell => transformTableCell(cell))
  };
};
exports.transformTableRow = transformTableRow;
const transformTable = node => {
  const {
    children: rows,
    align = []
  } = node;
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.TABLE,
    align: align,
    children: rows.map((row, index) => transformTableRow(row))
  };
};
exports.transformTable = transformTable;
const transformCodeLine = text => {
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.CODE_LINE,
    children: [{
      id: _slugid.default.nice(),
      text: text
    }]
  };
};
exports.transformCodeLine = transformCodeLine;
const transformCodeBlock = node => {
  const {
    lang,
    value
  } = node;
  let children = value.split('\n');
  if (children.length === 0) {
    children = [''];
  }
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.CODE_BLOCK,
    lang: lang,
    children: children.map(text => transformCodeLine(text))
  };
};
exports.transformCodeBlock = transformCodeBlock;
const transformDefinition = node => {
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.DEFINITION,
    identifier: node.identifier,
    url: node === null || node === void 0 ? void 0 : node.url,
    title: node === null || node === void 0 ? void 0 : node.title,
    children: [{
      id: _slugid.default.nice(),
      text: node === null || node === void 0 ? void 0 : node.title
    }]
  };
};
exports.transformDefinition = transformDefinition;
const transformHr = node => {
  return {
    id: _slugid.default.nice(),
    type: _elementTypes.DIVIDER,
    children: [(0, _core.generateDefaultText)()]
  };
};
exports.transformHr = transformHr;
const transformHtml = node => {
  const defaultTextNode = (0, _core.generateDefaultText)();
  if (node.value.slice(0, 4).toLowerCase() === '<img') {
    const {
      body
    } = new DOMParser().parseFromString(node.value, 'text/html');
    const img = body.firstChild;
    const src = img.getAttribute('src');
    if (!src) return [defaultTextNode];
    const alt = img.getAttribute('alt');
    const title = img.getAttribute('title');
    const width = img.getAttribute('width');
    const height = img.getAttribute('height');
    const data = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({
      src: src
    }, alt && {
      alt
    }), title && {
      title
    }), !isNaN(width) && width > 0 && {
      width
    }), !isNaN(height) && height > 0 && {
      height
    });
    const image = {
      id: _slugid.default.nice(),
      data: data,
      type: _elementTypes.IMAGE,
      children: [(0, _core.generateDefaultText)()]
    };
    return [(0, _core.generateDefaultText)(), image, (0, _core.generateDefaultText)()];
  }
  return [defaultTextNode];
};
exports.transformHtml = transformHtml;
const transformBlockHtml = node => {
  if (node.value.slice(0, 4).toLowerCase() === '<img') {
    return {
      id: _slugid.default.nice(),
      type: _elementTypes.PARAGRAPH,
      children: transformHtml(node)
    };
  }
  return (0, _htmlToSlate.default)(node.value);
};
exports.transformBlockHtml = transformBlockHtml;
const transformMath = node => {
  return {
    id: _slugid.default.nice(),
    type: 'formula',
    data: {
      formula: node.value
    },
    children: [(0, _core.generateDefaultText)()]
  };
};
exports.transformMath = transformMath;
const elementHandlers = {
  'paragraph': transformParagraph,
  'heading': transformHeader,
  'blockquote': transformBlockquote,
  'table': transformTable,
  'list': transformList,
  // ordered_list | unordered_list | check_list_item
  'code': transformCodeBlock,
  'thematicBreak': transformHr,
  'math': transformMath,
  'html': transformBlockHtml,
  'definition': transformDefinition
};
const formatMdToSlate = children => {
  const validChildren = children.filter(child => elementHandlers[child.type]);
  return validChildren.map(child => {
    const handler = elementHandlers[child.type];
    return handler(child);
  }).flat();
};
exports.formatMdToSlate = formatMdToSlate;