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

function NamedPipeServerTransport(config) {
    config = config || {};
    this.pipename = config.pipename;
    this.process = config.process;
    this.server = null;
}

//NamedPipeServerTransport.readMessage = function (socket, process, callback) {
//    var read = function (readCallback) {
//        while (null != (chunk = socket.read())) {
//            data = Buffer.concat([data, chunk]);
//        }
//        if (data.length > 0) {
//            readCallback()
//        }
//    };
//
//    socket.on('readable', function () {
//        var data = new Buffer(0);
//        var chunk;
//        var input;
//        var output;
//        while (null != (chunk = socket.read())) {
//            data = Buffer.concat([data, chunk]);
//        }
//        if (data.length > 0) {
//            input = new MemBuffer(new ArrayBuffer(data));
//            output = new Transport(socket);
//            me.process(input, output);
//        }
//    });
//    socket.on('error', function (err) {
//        callback(err);
//    });
//};

NamedPipeServerTransport.prototype.isMessageComplete = function (nodebuffer) {
    var input = new MemBuffer(new ArrayBuffer(nodebuffer));
    var output = new MemBuffer();
    var complete = true;
    var noop = true;
    try {
        this.process(input, output, noop);
    } catch (err) {
        if (err.message == 'MemBuffer overrun') complete = false;
    }
    return complete;
};

NamedPipeServerTransport.prototype.listen = function () {
    var me = this;

    this.server = net.createServer(function (socket) {
        var input = new AsyncMemBuffer();
        var firstByteReceived = false;

        socket.on('readable', function () {
            var chunk;
            var output;
            while (null != (chunk = socket.read())) {
                input.write(chunk);
                input.flush();

                if (chunk && chunk.length > 0 && !firstByteReceived) {
                    firstByteReceived = true;
                    input.on('readMessageEnd', function () {
                        input.clear();
                        firstByteReceived = false;
                    });
                    output = new Transport(socket);
                    me.process(input, output);
                }
            }
        });
		socket.on('error', function (err) {
			console.log('socket error: ' + err);
		});
    });
	
	this.server.on('error', function (err) {
		console.log('Server network error: ' + err);
	});

    this.server.listen(this.pipename);
};

NamedPipeServerTransport.prototype.old_listen = function () {
    var me = this;

    this.server = net.createServer(function (socket) {
        var data = new Buffer(0);
        socket.on('readable', function () {
            var chunk;
            var input;
            var output;
            while (null != (chunk = socket.read())) {
                data = Buffer.concat([data, chunk]);
            }
            if (data.length > 0) {
                if (me.isMessageComplete(data)) {
                    input = new MemBuffer(new ArrayBuffer(data));
                    output = new Transport(socket);
                    me.process(input, output);
                    data = new Buffer(0);
                }
            }
        });
        socket.on('error', function (err) {
            console.log('socket error: ' + err);
        });
    });
    
    this.server.on('error', function (err) {
        console.log('Server network error: ' + err);
    });

    this.server.listen(this.pipename);
};

NamedPipeServerTransport.prototype.close = function () {
    this.server.close();
};

function Transport(socket) {
    this.socket = socket;
    this.output = new MemBuffer();
}

Transport.prototype.write = function (bytes) {
    this.output.write(bytes);
};

Transport.prototype.clear = function (bytes) {
    this.output.clear();
};

Transport.prototype.flush = function () {
    this.output.flush();
	//this.socket.write(this.output.buffer);
    this.socket.end(this.output.buffer);
    this.clear();
};

exports.ServerTransport = NamedPipeServerTransport;

