'use strict';

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

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

var BufferList = require('bl');

var _require = require('readable-stream'),
    Duplex = _require.Duplex;

var _require2 = require('./packet'),
    Packet = _require2.Packet,
    HEADER_LENGTH = _require2.HEADER_LENGTH;

var OutgoingMessageStream = function (_Duplex) {
  (0, _inherits3.default)(OutgoingMessageStream, _Duplex);

  function OutgoingMessageStream(debug, _ref) {
    var packetSize = _ref.packetSize;
    (0, _classCallCheck3.default)(this, OutgoingMessageStream);

    var _this = (0, _possibleConstructorReturn3.default)(this, (OutgoingMessageStream.__proto__ || (0, _getPrototypeOf2.default)(OutgoingMessageStream)).call(this, { writableObjectMode: true }));

    _this.packetSize = packetSize;
    _this.debug = debug;
    _this.bl = new BufferList();

    // When the writable side is ended, push `null`
    // to also end the readable side.
    _this.on('finish', function () {
      _this.push(null);
    });
    return _this;
  }

  (0, _createClass3.default)(OutgoingMessageStream, [{
    key: '_write',
    value: function _write(message, encoding, callback) {
      var _this2 = this;

      var length = this.packetSize - HEADER_LENGTH;
      var packetNumber = 0;

      this.currentMessage = message;
      this.currentMessage.on('data', function (data) {
        _this2.bl.append(data);

        while (_this2.bl.length > length) {
          var _data = _this2.bl.slice(0, length);
          _this2.bl.consume(length);

          // TODO: Get rid of creating `Packet` instances here.
          var packet = new Packet(message.type);
          packet.packetId(packetNumber += 1);
          packet.resetConnection(message.resetConnection);
          packet.addData(_data);

          _this2.debug.packet('Sent', packet);
          _this2.debug.data(packet);

          if (_this2.push(packet.buffer) === false) {
            _this2.currentMessage.pause();
          }
        }
      });

      this.currentMessage.on('end', function () {
        var data = _this2.bl.slice();
        _this2.bl.consume(data.length);

        // TODO: Get rid of creating `Packet` instances here.
        var packet = new Packet(message.type);
        packet.packetId(packetNumber += 1);
        packet.resetConnection(message.resetConnection);
        packet.last(true);
        packet.addData(data);

        _this2.debug.packet('Sent', packet);
        _this2.debug.data(packet);

        _this2.push(packet.buffer);

        _this2.currentMessage = undefined;

        callback();
      });
    }
  }, {
    key: '_read',
    value: function _read(size) {
      // If we do have a message, resume it and get data flowing.
      // Otherwise, there is nothing to do.
      if (this.currentMessage) {
        this.currentMessage.resume();
      }
    }
  }]);
  return OutgoingMessageStream;
}(Duplex);

module.exports = OutgoingMessageStream;