// Generated by CoffeeScript 1.7.1
(function() {
  var LineWrapper;

  LineWrapper = require('../line_wrapper');

  module.exports = {
    initText: function() {
      this.x = 0;
      this.y = 0;
      return this._lineGap = 0;
    },
    lineGap: function(_lineGap) {
      this._lineGap = _lineGap;
      return this;
    },
    moveDown: function(lines) {
      if (lines == null) {
        lines = 1;
      }
      this.y += this.currentLineHeight(true) * lines + this._lineGap;
      return this;
    },
    moveUp: function(lines) {
      if (lines == null) {
        lines = 1;
      }
      this.y -= this.currentLineHeight(true) * lines + this._lineGap;
      return this;
    },
    _text: function(text, x, y, options, lineCallback) {
      var line, wrapper, _i, _len, _ref;
      options = this._initOptions(x, y, options);
      text = '' + text;
      if (options.wordSpacing) {
        text = text.replace(/\s{2,}/g, ' ');
      }
      if (options.width) {
        wrapper = this._wrapper;
        if (!wrapper) {
          wrapper = new LineWrapper(this, options);
          wrapper.on('line', lineCallback);
        }
        this._wrapper = options.continued ? wrapper : null;
        this._textOptions = options.continued ? options : null;
        wrapper.wrap(text, options);
      } else {
        _ref = text.split('\n');
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          line = _ref[_i];
          lineCallback(line, options);
        }
      }
      return this;
    },
    text: function(text, x, y, options) {
      return this._text(text, x, y, options, this._line.bind(this));
    },
    widthOfString: function(string, options) {
      if (options == null) {
        options = {};
      }
      return this._font.widthOfString(string, this._fontSize) + (options.characterSpacing || 0) * (string.length - 1);
    },
    heightOfString: function(text, options) {
      var height, lineGap, x, y;
      if (options == null) {
        options = {};
      }
      x = this.x, y = this.y;
      options = this._initOptions(options);
      options.height = Infinity;
      lineGap = options.lineGap || this._lineGap || 0;
      this._text(text, this.x, this.y, options, (function(_this) {
        return function(line, options) {
          return _this.y += _this.currentLineHeight(true) + lineGap;
        };
      })(this));
      height = this.y - y;
      this.x = x;
      this.y = y;
      return height;
    },
    list: function(list, x, y, options, wrapper) {
      var flatten, i, indent, itemIndent, items, level, levels, r;
      options = this._initOptions(x, y, options);
      r = Math.round((this._font.ascender / 1000 * this._fontSize) / 3);
      indent = options.textIndent || r * 5;
      itemIndent = options.bulletIndent || r * 8;
      level = 1;
      items = [];
      levels = [];
      flatten = function(list) {
        var i, item, _i, _len, _results;
        _results = [];
        for (i = _i = 0, _len = list.length; _i < _len; i = ++_i) {
          item = list[i];
          if (Array.isArray(item)) {
            level++;
            flatten(item);
            _results.push(level--);
          } else {
            items.push(item);
            _results.push(levels.push(level));
          }
        }
        return _results;
      };
      flatten(list);
      wrapper = new LineWrapper(this, options);
      wrapper.on('line', this._line.bind(this));
      level = 1;
      i = 0;
      wrapper.on('firstLine', (function(_this) {
        return function() {
          var diff, l;
          if ((l = levels[i++]) !== level) {
            diff = itemIndent * (l - level);
            _this.x += diff;
            wrapper.lineWidth -= diff;
            level = l;
          }
          _this.circle(_this.x - indent + r, _this.y + r + (r / 2), r);
          return _this.fill();
        };
      })(this));
      wrapper.on('sectionStart', (function(_this) {
        return function() {
          var pos;
          pos = indent + itemIndent * (level - 1);
          _this.x += pos;
          return wrapper.lineWidth -= pos;
        };
      })(this));
      wrapper.on('sectionEnd', (function(_this) {
        return function() {
          var pos;
          pos = indent + itemIndent * (level - 1);
          _this.x -= pos;
          return wrapper.lineWidth += pos;
        };
      })(this));
      wrapper.wrap(items.join('\n'), options);
      return this;
    },
    _initOptions: function(x, y, options) {
      var key, margins, val, _ref;
      if (x == null) {
        x = {};
      }
      if (options == null) {
        options = {};
      }
      if (typeof x === 'object') {
        options = x;
        x = null;
      }
      options = (function() {
        var k, opts, v;
        opts = {};
        for (k in options) {
          v = options[k];
          opts[k] = v;
        }
        return opts;
      })();
      if (this._textOptions) {
        _ref = this._textOptions;
        for (key in _ref) {
          val = _ref[key];
          if (key !== 'continued') {
            if (options[key] == null) {
              options[key] = val;
            }
          }
        }
      }
      if (x != null) {
        this.x = x;
      }
      if (y != null) {
        this.y = y;
      }
      if (options.lineBreak !== false) {
        margins = this.page.margins;
        if (options.width == null) {
          options.width = this.page.width - this.x - margins.right;
        }
      }
      options.columns || (options.columns = 0);
      if (options.columnGap == null) {
        options.columnGap = 18;
      }
      return options;
    },
    _line: function(text, options, wrapper) {
      var lineGap;
      if (options == null) {
        options = {};
      }
      this._fragment(text, this.x, this.y, options);
      lineGap = options.lineGap || this._lineGap || 0;
      if (!wrapper) {
        return this.x += this.widthOfString(text);
      } else {
        return this.y += this.currentLineHeight(true) + lineGap;
      }
    },
    _fragment: function(text, x, y, options) {
      var align, characterSpacing, commands, d, encoded, i, lineWidth, lineY, mode, renderedWidth, spaceWidth, textWidth, word, wordSpacing, words, _base, _i, _len, _name;
      text = '' + text;
      if (text.length === 0) {
        return;
      }
      align = options.align || 'left';
      wordSpacing = options.wordSpacing || 0;
      characterSpacing = options.characterSpacing || 0;
      if (options.width) {
        switch (align) {
          case 'right':
            textWidth = this.widthOfString(text.replace(/\s+$/, ''), options);
            x += options.lineWidth - textWidth;
            break;
          case 'center':
            x += options.lineWidth / 2 - options.textWidth / 2;
            break;
          case 'justify':
            words = text.trim().split(/\s+/);
            textWidth = this.widthOfString(text.replace(/\s+/g, ''), options);
            spaceWidth = this.widthOfString(' ') + characterSpacing;
            wordSpacing = Math.max(0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth);
        }
      }
      renderedWidth = options.textWidth + (wordSpacing * (options.wordCount - 1)) + (characterSpacing * (text.length - 1));
      if (options.link) {
        this.link(x, y, renderedWidth, this.currentLineHeight(), options.link);
      }
      if (options.underline || options.strike) {
        this.save();
        if (!options.stroke) {
          this.strokeColor.apply(this, this._fillColor);
        }
        lineWidth = this._fontSize < 10 ? 0.5 : Math.floor(this._fontSize / 10);
        this.lineWidth(lineWidth);
        d = options.underline ? 1 : 2;
        lineY = y + this.currentLineHeight() / d;
        if (options.underline) {
          lineY -= lineWidth;
        }
        this.moveTo(x, lineY);
        this.lineTo(x + renderedWidth, lineY);
        this.stroke();
        this.restore();
      }
      this.save();
      this.transform(1, 0, 0, -1, 0, this.page.height);
      y = this.page.height - y - (this._font.ascender / 1000 * this._fontSize);
      if ((_base = this.page.fonts)[_name = this._font.id] == null) {
        _base[_name] = this._font.ref();
      }
      this._font.use(text);
      this.addContent("BT");
      this.addContent("" + x + " " + y + " Td");
      this.addContent("/" + this._font.id + " " + this._fontSize + " Tf");
      mode = options.fill && options.stroke ? 2 : options.stroke ? 1 : 0;
      if (mode) {
        this.addContent("" + mode + " Tr");
      }
      if (characterSpacing) {
        this.addContent("" + characterSpacing + " Tc");
      }
      if (wordSpacing) {
        words = text.trim().split(/\s+/);
        wordSpacing += this.widthOfString(' ') + characterSpacing;
        wordSpacing *= 1000 / this._fontSize;
        commands = [];
        for (_i = 0, _len = words.length; _i < _len; _i++) {
          word = words[_i];
          encoded = this._font.encode(word);
          encoded = ((function() {
            var _j, _ref, _results;
            _results = [];
            for (i = _j = 0, _ref = encoded.length; _j < _ref; i = _j += 1) {
              _results.push(encoded.charCodeAt(i).toString(16));
            }
            return _results;
          })()).join('');
          commands.push("<" + encoded + "> " + (-wordSpacing));
        }
        this.addContent("[" + (commands.join(' ')) + "] TJ");
      } else {
        encoded = this._font.encode(text);
        encoded = ((function() {
          var _j, _ref, _results;
          _results = [];
          for (i = _j = 0, _ref = encoded.length; _j < _ref; i = _j += 1) {
            _results.push(encoded.charCodeAt(i).toString(16));
          }
          return _results;
        })()).join('');
        this.addContent("<" + encoded + "> Tj");
      }
      this.addContent("ET");
      return this.restore();
    }
  };

}).call(this);
