// Generated by CoffeeScript 1.9.3
var AnsiPainter, object, styles, tags, tools,
  hasProp = {}.hasOwnProperty,
  slice = [].slice;

tools = require('./tools');

tags = require('./ansiPainter/tags');

styles = require('./ansiPainter/styles');

object = require('utila').object;

module.exports = AnsiPainter = (function() {
  var self;

  function AnsiPainter() {}

  AnsiPainter.tags = tags;

  AnsiPainter.prototype.paint = function(s) {
    return this._replaceSpecialStrings(this._renderDom(this._parse(s)));
  };

  AnsiPainter.prototype._replaceSpecialStrings = function(str) {
    return str.replace(/&sp;/g, ' ').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&amp;/g, '&');
  };

  AnsiPainter.prototype._parse = function(string, injectFakeRoot) {
    if (injectFakeRoot == null) {
      injectFakeRoot = true;
    }
    if (injectFakeRoot) {
      string = '<none>' + string + '</none>';
    }
    return tools.toDom(string);
  };

  AnsiPainter.prototype._renderDom = function(dom) {
    var parentStyles;
    parentStyles = {
      bg: 'none',
      color: 'none'
    };
    return this._renderChildren(dom, parentStyles);
  };

  AnsiPainter.prototype._renderChildren = function(children, parentStyles) {
    var child, n, ret;
    ret = '';
    for (n in children) {
      if (!hasProp.call(children, n)) continue;
      child = children[n];
      ret += this._renderNode(child, parentStyles);
    }
    return ret;
  };

  AnsiPainter.prototype._renderNode = function(node, parentStyles) {
    if (node.type === 'text') {
      return this._renderTextNode(node, parentStyles);
    } else {
      return this._renderTag(node, parentStyles);
    }
  };

  AnsiPainter.prototype._renderTextNode = function(node, parentStyles) {
    return this._wrapInStyle(node.data, parentStyles);
  };

  AnsiPainter.prototype._wrapInStyle = function(str, style) {
    return styles.color(style.color) + styles.bg(style.bg) + str + styles.none();
  };

  AnsiPainter.prototype._renderTag = function(node, parentStyles) {
    var currentStyles, tagStyles;
    tagStyles = this._getStylesForTagName(node.name);
    currentStyles = this._mixStyles(parentStyles, tagStyles);
    return this._renderChildren(node.children, currentStyles);
  };

  AnsiPainter.prototype._mixStyles = function() {
    var final, i, key, len, style, styles, val;
    styles = 1 <= arguments.length ? slice.call(arguments, 0) : [];
    final = {};
    for (i = 0, len = styles.length; i < len; i++) {
      style = styles[i];
      for (key in style) {
        if (!hasProp.call(style, key)) continue;
        val = style[key];
        if ((final[key] == null) || val !== 'inherit') {
          final[key] = val;
        }
      }
    }
    return final;
  };

  AnsiPainter.prototype._getStylesForTagName = function(name) {
    if (tags[name] == null) {
      throw Error("Unknown tag name `" + name + "`");
    }
    return tags[name];
  };

  self = AnsiPainter;

  AnsiPainter.getInstance = function() {
    if (self._instance == null) {
      self._instance = new self;
    }
    return self._instance;
  };

  AnsiPainter.paint = function(str) {
    return self.getInstance().paint(str);
  };

  AnsiPainter.strip = function(s) {
    return s.replace(/\x1b\[[0-9]+m/g, '');
  };

  return AnsiPainter;

})();
