// Generated by CoffeeScript 1.9.3
var $, SPACES_ONLY, Serialiser, TEXT_LEADING_WHITESPACE, TEXT_TRAILING_WHITESPACE, WHITESPACE_ONLY, componentClassTagConvention, containsNewlines, entityDecode, exports, find, firstNonWhitespaceChild, genericBranchSerialiser, genericLeafSerialiser, joinList, last, nodeSerialisers, ref, serialise, stringEscape;

ref = require('./helpers'), last = ref.last, find = ref.find;

$ = require('./symbols');

stringEscape = require('./stringescape');

entityDecode = require('./entitydecode');

module.exports = exports = serialise = function(parseTree) {
  return new Serialiser().serialise(parseTree);
};

Serialiser = (function() {
  function Serialiser() {}

  Serialiser.prototype.serialise = function(parseTree) {
    var domObjectParts;
    if (parseTree.children && parseTree.children.length && parseTree.children[0].type === $.CJSX_PRAGMA) {
      this.domObject = parseTree.children[0].value;
    } else {
      this.domObject = 'React.DOM';
    }
    domObjectParts = this.domObject.split('.');
    if (domObjectParts.length > 0 && domObjectParts[0] !== '') {
      this.reactObject = domObjectParts[0];
    } else {
      this.reactObject = 'React';
    }
    return this.serialiseNode(parseTree);
  };

  Serialiser.prototype.serialiseNode = function(node) {
    var serialised;
    if (nodeSerialisers[node.type] == null) {
      throw new Error("unknown parseTree node type " + node.type);
    }
    serialised = nodeSerialisers[node.type].call(this, node);
    if (!(typeof serialised === 'string' || serialised === null)) {
      throw new Error("serialiser " + node.type + " didn\'t return a string");
    }
    return serialised;
  };

  Serialiser.prototype.serialiseSpreadAndPairAttributes = function(children) {
    var accumulatedWhitespace, assignIndex, assignItem, assigns, assignsWithWhitespace, child, childIndex, flushPairs, j, joinedAssigns, k, lastAssignWithWhitespace, len, len1, pairAttrsBuffer, ref1, trailingWhiteplace;
    assigns = [];
    pairAttrsBuffer = [];
    flushPairs = (function(_this) {
      return function() {
        var serialisedChild, serialisedPairs;
        if (pairAttrsBuffer.length) {
          serialisedChild = _this.serialiseAttributePairs(pairAttrsBuffer);
          if (serialisedChild) {
            assigns.push({
              type: $.CS,
              value: serialisedChild
            });
          } else {
            serialisedPairs = pairAttrsBuffer.map(function(p) {
              return _this.serialiseNode(p);
            }).join('').replace('\n', '\\\n');
            assigns.push({
              type: $.CJSX_WHITESPACE,
              value: serialisedPairs
            });
          }
          return pairAttrsBuffer = [];
        }
      };
    })(this);
    if (((ref1 = firstNonWhitespaceChild(children)) != null ? ref1.type : void 0) === $.CJSX_ATTR_SPREAD) {
      assigns.push({
        type: $.CS,
        value: '{}'
      });
    }
    for (childIndex = j = 0, len = children.length; j < len; childIndex = ++j) {
      child = children[childIndex];
      if (child.type === $.CJSX_ATTR_SPREAD) {
        flushPairs();
        assigns.push({
          type: $.CS,
          value: child.value
        });
      } else {
        pairAttrsBuffer.push(child);
      }
    }
    flushPairs();
    accumulatedWhitespace = '';
    assignsWithWhitespace = [];
    for (assignIndex = k = 0, len1 = assigns.length; k < len1; assignIndex = ++k) {
      assignItem = assigns[assignIndex];
      if (assignItem != null) {
        if (assignItem.type === $.CJSX_WHITESPACE) {
          accumulatedWhitespace += this.serialiseNode(assignItem);
        } else {
          assignsWithWhitespace.push(accumulatedWhitespace + this.serialiseNode(assignItem));
          accumulatedWhitespace = '';
        }
      }
    }
    if (assignsWithWhitespace.length) {
      lastAssignWithWhitespace = assignsWithWhitespace.pop();
      trailingWhiteplace = accumulatedWhitespace.replace('\\\n', '\n');
      assignsWithWhitespace.push(lastAssignWithWhitespace + trailingWhiteplace);
    }
    joinedAssigns = joinList(assignsWithWhitespace);
    return "React.__spread(" + (joinList(assignsWithWhitespace)) + ")";
  };

  Serialiser.prototype.serialiseAttributePairs = function(children) {
    var child, childIndex, indexOfLastSemanticChild, isBeforeLastSemanticChild, ref1, semanticChildren, serialisedChild, serialisedChildren, whitespaceChildren;
    ref1 = children.reduce(function(partitionedChildren, child) {
      if (child.type === $.CJSX_WHITESPACE) {
        partitionedChildren[0].push(child);
      } else {
        partitionedChildren[1].push(child);
      }
      return partitionedChildren;
    }, [[], []]), whitespaceChildren = ref1[0], semanticChildren = ref1[1];
    indexOfLastSemanticChild = children.lastIndexOf(last(semanticChildren));
    isBeforeLastSemanticChild = function(childIndex) {
      return childIndex < indexOfLastSemanticChild;
    };
    if (semanticChildren.length) {
      serialisedChildren = (function() {
        var j, len, results;
        results = [];
        for (childIndex = j = 0, len = children.length; j < len; childIndex = ++j) {
          child = children[childIndex];
          serialisedChild = this.serialiseNode(child);
          if (child.type === $.CJSX_WHITESPACE) {
            if (containsNewlines(serialisedChild)) {
              if (isBeforeLastSemanticChild(childIndex)) {
                results.push(serialisedChild.replace('\n', ' \\\n'));
              } else {
                results.push(serialisedChild);
              }
            } else {
              results.push(null);
            }
          } else if (isBeforeLastSemanticChild(childIndex)) {
            results.push(serialisedChild + ', ');
          } else {
            results.push(serialisedChild);
          }
        }
        return results;
      }).call(this);
      return '{' + serialisedChildren.join('') + '}';
    } else {
      return null;
    }
  };

  return Serialiser;

})();

genericBranchSerialiser = function(node) {
  return node.children.map((function(_this) {
    return function(child) {
      return _this.serialiseNode(child);
    };
  })(this)).join('');
};

genericLeafSerialiser = function(node) {
  return node.value;
};

componentClassTagConvention = /(^[A-Z@]|\.)/;

nodeSerialisers = {
  ROOT: genericBranchSerialiser,
  CJSX_PRAGMA: function() {
    return "`/** @jsx " + this.domObject + " */`";
  },
  CJSX_EL: function(node) {
    var accumulatedWhitespace, child, element, j, len, ref1, serialisedChild, serialisedChildren;
    serialisedChildren = [];
    accumulatedWhitespace = '';
    ref1 = node.children;
    for (j = 0, len = ref1.length; j < len; j++) {
      child = ref1[j];
      serialisedChild = this.serialiseNode(child);
      if (child != null) {
        if (serialisedChild.length === 0 || WHITESPACE_ONLY.test(serialisedChild)) {
          accumulatedWhitespace += serialisedChild;
        } else {
          serialisedChildren.push(accumulatedWhitespace + serialisedChild);
          accumulatedWhitespace = '';
        }
      }
    }
    if (serialisedChildren.length) {
      serialisedChildren[serialisedChildren.length - 1] += accumulatedWhitespace;
      accumulatedWhitespace = '';
    }
    if (componentClassTagConvention.test(node.value)) {
      element = node.value;
    } else {
      element = '"' + node.value + '"';
    }
    return this.reactObject + ".createElement(" + element + ", " + (joinList(serialisedChildren)) + ")";
  },
  CJSX_COMMENT: function(node) {
    return '';
  },
  CJSX_ESC: function(node) {
    var childrenSerialised;
    childrenSerialised = node.children.map((function(_this) {
      return function(child) {
        return _this.serialiseNode(child);
      };
    })(this)).join('');
    return '(' + childrenSerialised + ')';
  },
  CJSX_ATTRIBUTES: function(node) {
    if (node.children.some(function(child) {
      return child.type === $.CJSX_ATTR_SPREAD;
    })) {
      return this.serialiseSpreadAndPairAttributes(node.children);
    } else {
      return this.serialiseAttributePairs(node.children) || 'null';
    }
  },
  CJSX_ATTR_PAIR: function(node) {
    return node.children.map((function(_this) {
      return function(child) {
        return _this.serialiseNode(child);
      };
    })(this)).join(': ');
  },
  CJSX_ATTR_SPREAD: function(node) {
    return node.value;
  },
  CS: genericLeafSerialiser,
  CS_COMMENT: genericLeafSerialiser,
  CS_HEREDOC: genericLeafSerialiser,
  CS_STRING: genericLeafSerialiser,
  CS_REGEX: genericLeafSerialiser,
  CS_HEREGEX: genericLeafSerialiser,
  JS_ESC: genericLeafSerialiser,
  CJSX_WHITESPACE: genericLeafSerialiser,
  CJSX_TEXT: function(node) {
    var escapedText, leftSpace, leftTrim, rightSpace, rightTrim, text, trimmedText;
    text = node.value;
    if (containsNewlines(text)) {
      if (WHITESPACE_ONLY.test(text)) {
        return text;
      } else {
        leftSpace = text.match(TEXT_LEADING_WHITESPACE);
        rightSpace = text.match(TEXT_TRAILING_WHITESPACE);
        if (leftSpace) {
          leftTrim = text.indexOf('\n');
        } else {
          leftTrim = 0;
        }
        if (rightSpace) {
          rightTrim = text.lastIndexOf('\n') + 1;
        } else {
          rightTrim = text.length;
        }
        trimmedText = text.substring(leftTrim, rightTrim);
        escapedText = stringEscape(entityDecode(trimmedText), {
          preserveNewlines: true
        });
        return '"""' + escapedText + '"""';
      }
    } else {
      if (text === '') {
        return null;
      } else {
        return '"' + stringEscape(entityDecode(text)) + '"';
      }
    }
  },
  CJSX_ATTR_KEY: genericLeafSerialiser,
  CJSX_ATTR_VAL: genericLeafSerialiser
};

firstNonWhitespaceChild = function(children) {
  return find.call(children, function(child) {
    return child.type !== $.CJSX_WHITESPACE;
  });
};

containsNewlines = function(text) {
  return text.indexOf('\n') > -1;
};

joinList = function(items) {
  var i, output;
  output = items[items.length - 1];
  i = items.length - 2;
  while (i >= 0) {
    if (output.charAt(0) === '\n') {
      output = items[i] + ',' + output;
    } else {
      output = items[i] + ', ' + output;
    }
    i--;
  }
  return output;
};

SPACES_ONLY = /^\s+$/;

WHITESPACE_ONLY = /^[\n\s]+$/;

TEXT_LEADING_WHITESPACE = /^\s*?\n\s*/;

TEXT_TRAILING_WHITESPACE = /\s*?\n\s*?$/;

exports.Serialiser = Serialiser;

exports.nodeSerialisers = nodeSerialisers;
