'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _yogaLayout = require('yoga-layout');

var _yogaLayout2 = _interopRequireDefault(_yogaLayout);

var _Base2 = require('./Base');

var _Base3 = _interopRequireDefault(_Base2);

var _TextEngine = require('./TextEngine');

var _TextEngine2 = _interopRequireDefault(_TextEngine);

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

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var WIDOW_THREASHOLD = 20;

var Text = function (_Base) {
  _inherits(Text, _Base);

  function Text(root, props) {
    _classCallCheck(this, Text);

    var _this = _possibleConstructorReturn(this, (Text.__proto__ || Object.getPrototypeOf(Text)).call(this, root, props));

    _this.engine = new _TextEngine2.default(_this);
    _this.layout.setMeasureFunc(_this.measureText.bind(_this));
    _this.renderCallback = props.render;
    return _this;
  }

  _createClass(Text, [{
    key: 'appendChild',
    value: function appendChild(child) {
      if (typeof child === 'string') {
        this.children.push(child);
      } else {
        child.parent = this;
        this.children.push(child);
      }
    }
  }, {
    key: 'removeChild',
    value: function removeChild(child) {
      this.children = null;
    }
  }, {
    key: 'measureText',
    value: function measureText(width, widthMode, height, heightMode) {
      // If the text has functions inside, we don't measure dimentions right away,
      // but we keep this until all functions are resolved after the layout stage.
      if (this.renderCallback) {
        return {};
      }

      if (widthMode === _yogaLayout2.default.MEASURE_MODE_EXACTLY) {
        this.engine.layout(width);

        return {
          height: this.style.flexGrow ? NaN : this.engine.height
        };
      }

      if (widthMode === _yogaLayout2.default.MEASURE_MODE_AT_MOST || heightMode === _yogaLayout2.default.MEASURE_MODE_AT_MOST) {
        this.engine.layout(width);

        return {
          height: this.engine.height,
          width: Math.min(width, this.engine.width)
        };
      }

      return {};
    }
  }, {
    key: 'recalculateLayout',
    value: function recalculateLayout() {
      this.layout.markDirty();
    }
  }, {
    key: 'isEmpty',
    value: function isEmpty() {
      return this.engine.lines.length === 0;
    }
  }, {
    key: 'hasOrphans',
    value: function hasOrphans(linesQuantity, slicedLines) {
      return slicedLines === 1 && linesQuantity !== 1;
    }
  }, {
    key: 'hasWidows',
    value: function hasWidows(linesQuantity, slicedLines) {
      return linesQuantity !== 1 && linesQuantity - slicedLines === 1 && linesQuantity < WIDOW_THREASHOLD;
    }
  }, {
    key: 'wrapHeight',
    value: function wrapHeight(height) {
      var _props = this.props,
          orphans = _props.orphans,
          widows = _props.widows;

      var linesQuantity = this.engine.lines.length;
      var sliceHeight = height - this.marginTop - this.paddingTop;
      var slicedLines = this.engine.lineIndexAtHeight(sliceHeight);

      var wrapHeight = height;

      if (linesQuantity < orphans) {
        wrapHeight = height;
      } else if (slicedLines < orphans || linesQuantity < orphans + widows) {
        wrapHeight = 0;
      } else if (linesQuantity === orphans + widows) {
        wrapHeight = this.engine.heightAtLineIndex(orphans - 1);
      } else if (linesQuantity - slicedLines < widows) {
        wrapHeight = height - this.engine.heightAtLineIndex(widows - 1);
      }

      return Math.min(wrapHeight, this.height);
    }
  }, {
    key: 'splice',
    value: function splice(height) {
      var wrapHeight = this.wrapHeight(height);
      var engine = this.engine.splice(wrapHeight);
      var result = this.clone();

      result.marginTop = 0;
      result.paddingTop = 0;
      result.width = this.width;
      result.marginBottom = this.marginBottom;
      result.engine = engine;
      result.engine.element = result;
      result.height = engine.height + this.paddingBottom + this.marginBottom;

      this.marginBottom = 0;
      this.paddingBottom = 0;
      this.height = height;

      return result;
    }
  }, {
    key: 'render',
    value: function () {
      var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(page) {
        return regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                this.drawBackgroundColor();
                this.drawBorders();

                if (this.props.debug) {
                  this.debug();
                }

                this.engine.render();

              case 4:
              case 'end':
                return _context.stop();
            }
          }
        }, _callee, this);
      }));

      function render(_x) {
        return _ref.apply(this, arguments);
      }

      return render;
    }()
  }, {
    key: 'src',
    get: function get() {
      return null;
    }
  }]);

  return Text;
}(_Base3.default);

Text.defaultProps = {
  wrap: true,
  widows: 2,
  orphans: 2
};
exports.default = Text;