var LINE_ENDING_SPLITER = /\r\n|\r|\n/;
var EMPTY_LINE = '';
var NOTE_MARK_START = '<!--Note-->';
var NOTE_MARK_CLOSE = '<!--/Note-->';

function exportMarkdown(minder) {
  var minds = minder.exportJson();
  try {
    const link = document.createElement('a');
    const blob = new Blob(["\ufeff" + encode(minds.root, 0)], {
      type: 'markdown'
    });
    link.href = window.URL.createObjectURL(blob);
    link.download = `${minds.root.data.text}.md`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  } catch (err) {
    console.log(err);
  }
}

function encode(json) {
  return _build(json, 1).join('\n');
}

function _build(node, level) {
  var lines = [];

  level = level || 1;

  var sharps = _generateHeaderSharp(level);
  lines.push(sharps + ' ' + node.data.text);
  lines.push(EMPTY_LINE);

  var note = node.data.note;
  if (note) {
    var hasSharp = /^#/.test(note);
    if (hasSharp) {
      lines.push(NOTE_MARK_START);
      note = note.replace(/^#+/gm, function ($0) {
        return sharps + $0;
      });
    }
    lines.push(note);
    if (hasSharp) {
      lines.push(NOTE_MARK_CLOSE);
    }
    lines.push(EMPTY_LINE);
  }

  if (node.children) node.children.forEach(function (child) {
    lines = lines.concat(_build(child, level + 1));
  });

  return lines;
}

function _generateHeaderSharp(level) {
  var sharps = '';
  while (level--) sharps += '#';
  return sharps;
}

function decode(markdown) {

  var json,
    parentMap = {},
    lines, line, lineInfo, level, node, parent, noteProgress, codeBlock;

  // 一级标题转换 `{title}\n===` => `# {title}`
  markdown = markdown.replace(/^(.+)\n={3,}/, function ($0, $1) {
    return '# ' + $1;
  });

  lines = markdown.split(LINE_ENDING_SPLITER);

  // 按行分析
  for (var i = 0; i < lines.length; i++) {
    line = lines[i];

    lineInfo = _resolveLine(line);

    // 备注标记处理
    if (lineInfo.noteClose) {
      noteProgress = false;
      continue;
    } else if (lineInfo.noteStart) {
      noteProgress = true;
      continue;
    }

    // 代码块处理
    codeBlock = lineInfo.codeBlock ? !codeBlock : codeBlock;

    // 备注条件：备注标签中，非标题定义，或标题越位
    if (noteProgress || codeBlock || !lineInfo.level || lineInfo.level > level + 1) {
      if (node) _pushNote(node, line);
      continue;
    }

    // 标题处理
    level = lineInfo.level;
    node = _initNode(lineInfo.content, parentMap[level - 1]);
    parentMap[level] = node;
  }

  _cleanUp(parentMap[1]);
  return parentMap[1];
}

function _initNode(text, parent) {
  var node = {
    data: {
      text: text,
      note: ''
    }
  };
  if (parent) {
    if (parent.children) parent.children.push(node);
    else parent.children = [node];
  }
  return node;
}

function _pushNote(node, line) {
  node.data.note += line + '\n';
}

function _isEmpty(line) {
  return !/\S/.test(line);
}

function _resolveLine(line) {
  var match = /^(#+)?\s*(.*)$/.exec(line);
  return {
    level: match[1] && match[1].length || null,
    content: match[2],
    noteStart: line == NOTE_MARK_START,
    noteClose: line == NOTE_MARK_CLOSE,
    codeBlock: /^\s*```/.test(line)
  };
}

function _cleanUp(node) {
  if (!/\S/.test(node.data.note)) {
    node.data.note = null;
    delete node.data.note;
  } else {
    var notes = node.data.note.split('\n');
    while (notes.length && !/\S/.test(notes[0])) notes.shift();
    while (notes.length && !/\S/.test(notes[notes.length - 1])) notes.pop();
    node.data.note = notes.join('\n');
  }
  if (node.children) node.children.forEach(_cleanUp);
}

export {
  exportMarkdown
}
