var ArrayBuffer = require('./typedarrays').ArrayBuffer;
var MemBuffer = require('./MemBuffer').Buffer;
var AsyncMemBuffer = require('./AsyncMemBuffer').Buffer;
var net = require('net');

global.namedPipeQueue = global.namedPipeQueue || [];

function NamedPipeTransport (pipename) {
    this.pipename = pipename;
    this.input = new MemBuffer();
    this.queue = global.namedPipeQueue;
};

NamedPipeTransport.prototype.open = function () {
};

NamedPipeTransport.prototype.close = function () {
};

NamedPipeTransport.prototype.read = function (len) {
    throw Error('NamedPipeTransport object does not support reads');
};

NamedPipeTransport.prototype.write = function (bytes) {
    this.input.write(bytes);
};

NamedPipeTransport.prototype.clear = function () {
    this.input.clear();
};

NamedPipeTransport.prototype.isMessageComplete = function (nodebuffer, onsuccess) {
    var data = new MemBuffer(new ArrayBuffer(nodebuffer));
    var complete = true;
    onsuccess(data, function () {
        complete = false;
    });
    return complete;
};

NamedPipeTransport.prototype.flush = function (onsuccess, onerror) {
    onerror = onerror || onsuccess;

    this.input.flush();
    var request = {
        onsuccess: onsuccess,
        onerror: onerror,
        buffer: this.input.buffer
    };
    this.queue.push(request);
    this.clear();

    if (this.queue.length == 1) this.send(request.buffer, onsuccess, onerror);
};

NamedPipeTransport.prototype.send = function send(buffer, onsuccess, onerror) {
    var me = this;
    var socket = net.connect(this.pipename);
    var response = new AsyncMemBuffer();
    var firstByteReceived = false;

    if (!send.start) send.start = Date.now();
    // response.perfstart = Date.now();
    // response.chunks = 0;

    socket.on('connect', function (err) {
        if (err) return console.log(err);
        socket.write(buffer);
        send.start = null;
    });

    socket.on('data', function (chunk) {
        response.write(chunk);
        response.flush();
        //response.chunks++;

        if (!firstByteReceived) {
            firstByteReceived = true;
            send.start = null;
            response.on('readMessageEnd', function () {
                response = null;
                socket.destroy();
                send.start = null;
                me.next();
            });
            onsuccess(response);
        }
    });

    socket.on('error', function (err) {
        if (Date.now() - send.start < 3000) {
            console.log('Retrying request at ' + Date.now());
            setImmediate(me.send.bind(me, buffer, onsuccess, onerror));
        } else {
            console.log('Problem with request in NamedPipeTransport: ' + err.message);
            if (onerror && typeof onerror == 'function') onerror(err);
            send.start = null;
            me.next();
        }
    });
};

NamedPipeTransport.prototype.next = function () {
    var request;
    var me = this;
    this.queue.shift();
    if (this.queue.length > 0) {
        request = this.queue[0];
        setImmediate(me.send.bind(me, request.buffer, request.onsuccess, request.onerror));
    }
};

exports.Transport = NamedPipeTransport;

