var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Promise = require('bluebird');

function AsyncMemBuffer(buffer) {
    EventEmitter.call(this);

    this.writes = [];
    this.reads = [];
    this.buffer = buffer;
    this.offset = 0;
    this.length = buffer ? buffer.length : 0;
};

util.inherits(AsyncMemBuffer, EventEmitter);

AsyncMemBuffer.prototype.read = function (len) {
    var me = this;
    var promise = new Promise(function (resolve, reject) {
        me.reads.push({len: len, resolve: resolve, reject: reject});
        me.attemptReads();
    });
    return promise;
};

AsyncMemBuffer.prototype.attemptReads = function () {
    var request;
    var buffer;
    while (this.reads.length > 0 && this.reads[0].len + this.offset <= this.length) {
        request = this.reads.shift();
        if (this.offset + request.len > this.buffer.length) {
            request.reject(Error('AsyncMemBuffer overrun'));
        } else {
            buffer = this.buffer.slice(this.offset, this.offset + request.len);
            this.offset += request.len;
            request.resolve(buffer);
        }
    }
};

AsyncMemBuffer.prototype.write = function (buffer) {
    if (Buffer.isBuffer(buffer)) {
        this.writes.push(buffer);
    } else {
        throw Error('Unsupported type sent to AsyncMemBuffer.write. Accepts Buffer.');
    }
};

AsyncMemBuffer.prototype.clear = function () {
    this.writes = [];
    this.reads = [];
    this.buffer = null;
    this.offset = 0;
    this.length = 0;
};

AsyncMemBuffer.prototype.flush = function () {
    if (this.buffer) this.writes.unshift(this.buffer);
    this.buffer = Buffer.concat(this.writes);
    this.writes = [];
    this.length = this.buffer.length;
    this.attemptReads();
};

module.exports = AsyncMemBuffer;
