'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});
exports.writeHtmlAsDom = writeHtmlAsDom;
exports['default'] = writeHtml;

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _attributes = require('./attributes');

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _reactLibCSSPropertyOperations = require('react/lib/CSSPropertyOperations');

var _reactLibCSSPropertyOperations2 = _interopRequireDefault(_reactLibCSSPropertyOperations);

function styleForAttributes(attributes) {
  var hasAttribute = (0, _attributes.hasAttributeFor)(attributes);

  var style = {};
  var superscript = hasAttribute(_attributes.ATTR.SUPERSCRIPT);
  var subscript = hasAttribute(_attributes.ATTR.SUBSCRIPT);
  if (superscript || subscript) {
    style.verticalAlign = (0, _classnames2['default'])({
      'super': superscript,
      sub: subscript
    });
  }

  // font size, weight, style
  //let fontSize = this.fontSizeFromAttributes(this.props.fontSize, attributes)

  if (hasAttribute(_attributes.ATTR.BOLD)) {
    style.fontWeight = 'bold';
  }
  if (hasAttribute(_attributes.ATTR.ITALIC)) {
    style.fontStyle = 'italic';
  }

  // text-decoration
  var underline = hasAttribute(_attributes.ATTR.UNDERLINE);
  var strikethrough = hasAttribute(_attributes.ATTR.STRIKETHROUGH);

  if (underline || strikethrough) {
    style.textDecoration = (0, _classnames2['default'])({
      underline: underline,
      'line-through': strikethrough
    });
  }

  return style;
}

function setStyle(el, style, preserveWhitespace) {
  if (preserveWhitespace) {
    style.whiteSpace = 'pre-wrap';
  }
  var cssString = _reactLibCSSPropertyOperations2['default'].createMarkupForStyles(style);
  el.setAttribute('style', cssString);
}

/**
 * Writes chunks of rich text into an HTML document.
 *
 * @param {Array} chunks The rich text chunks to write.
 */

function writeHtmlAsDom(chunks) {
  var html = document.createDocumentFragment();

  if (!chunks) {
    chunks = [];
  }

  var pendingChunks = [];

  var pushToHtml = function pushToHtml(fragment) {
    html.appendChild(fragment);
  };

  var createSpan = function createSpan(chunk) {
    var textNode = document.createTextNode(chunk.text);
    var span = document.createElement('SPAN');
    span.appendChild(textNode);
    setStyle(span, styleForAttributes(chunk.attrs), true);
    return span;
  };

  var pushBreakToHtml = function pushBreakToHtml() {
    pushToHtml(document.createElement('BR'));
  };

  var pushSpansToHtml = function pushSpansToHtml() {
    if (pendingChunks.length === 0) {
      return;
    }
    var spans = pendingChunks.map(createSpan);
    var fragment = document.createDocumentFragment();
    spans.forEach(function (s) {
      return fragment.appendChild(s);
    });
    pushToHtml(fragment);
    pendingChunks = [];
  };

  var pushParaToHtml = function pushParaToHtml() {
    if (pendingChunks.length === 0) {
      return;
    }
    var para = document.createElement('P');
    if (pendingChunks.length > 1) {
      // encapsulate chunks in styled spans
      var spans = pendingChunks.map(createSpan);
      spans.forEach(function (s) {
        return para.appendChild(s);
      });
    } else if (pendingChunks.length === 1) {
      // encapsulate chunk in styled para
      var textNode = document.createTextNode(pendingChunks[0].text);
      para.appendChild(textNode);
      setStyle(para, styleForAttributes(pendingChunks[0].attrs), true);
    }
    pushToHtml(para);
    pendingChunks = [];
  };

  var newlineCount = 0;
  var paraClean = true;

  var handleNewlines = function handleNewlines(atEnd) {
    if (newlineCount > 0) {
      if (newlineCount >= 2) {
        // a bunch of newlines in a row, we need to push a paragraph for the first two and assume the rest are breaks
        // see http://www.w3.org/TR/html5/dom.html#palpable-content
        pushParaToHtml(pendingChunks);
        paraClean = false;
        if (atEnd) {
          // add line breaks too
          while (newlineCount > 0) {
            pushBreakToHtml();
            newlineCount--;
          }
        } else {
          newlineCount -= 2;
        }
      }
      // treat any more newlines as line breaks
      while (newlineCount > 0) {
        pushSpansToHtml(pendingChunks);
        pushBreakToHtml();
        newlineCount--;
      }
    }
  };

  chunks.forEach(function (c) {
    if (c.text === '\n') {
      newlineCount++;
    } else {
      handleNewlines(false);
      pendingChunks.push(c);
    }
  });

  // trailing newlines
  handleNewlines(true);

  if (paraClean) {
    pushSpansToHtml(pendingChunks);
  } else {
    pushParaToHtml(pendingChunks);
  }

  return html;
}

/**
 * Writes chunks of rich text into an HTML document.
 *
 * @param {Array} chunks The rich text chunks to write.
 */

function writeHtml(chunks) {
  var html = writeHtmlAsDom(chunks);

  // fragments don't have an innerHTML method so we need to wrap it in another container first
  var container = document.createElement('div');
  container.appendChild(html);
  return container.innerHTML;
}