whole_func_string: function Client (opts) {
  	this.id = opts.id;
  	this.opts = opts;
  	this.send = send; 
  	this.isConnected = false;
  	let client = this;
  
  	let queue = [];
  	let callbacks = {};
  	let isBusy = true;
  	let socket;
  
  	connect(opts);
  
  	function send (event, data, callback) {
  		if (!client.isConnected && callback)
  			return callback(new Error('CONNECTION'));
  
  		queue.push({event, data, callback});
  		next();
  	}
  
  	function next() {
  		if (isBusy)
  			return;
  		
  		isBusy = true;
  
  		if (queue.length == 0) 
  			return (isBusy = false);
  
  		if (socket) {
  			let msg = {
  				id: genId(),
  				event: queue[0].event, 
  				data: queue[0].data
  			}
  
  			socket.write((!!opts.cipher ? encode(JSON.stringify(msg), opts.cipher, opts.password) : JSON.stringify(msg)) + '|', function (err) {
  				if (err)
  					return socket.emit('error', err);
  
  				if (queue[0].callback)		
  					callbacks[msg.id] = queue[0].callback;
  
  				client.emit('send', queue[0]);
  				queue.shift(); 
  				isBusy = false;
  				next();
  			});
  		}	
  	}
  	
  	function connect (opts) {
  		socket = net.connect({host: opts.host, port: opts.port});
  		queue = [];
  		callbacks = {};
  		isBusy = true;
  
  		socket.on('connect', function () {
  			isBusy = false;
  			client.isConnected = true;
  			client.emit('connect', opts.id);
  		});
  
  		let buffer = '';
  		socket.on('data', function(chunk) {
  			buffer += chunk;
  			let msgs = buffer.split('|');
  			buffer = msgs.pop();
  
  			msgs.forEach(function(packet){
  
  				let msg;
  				try { 
  					msg = JSON.parse(!!opts.cipher ? decode(packet, opts.cipher, opts.password) : packet);
  				} catch(err) { 
  					return socket.emit('error', err);
  				}
  
  				client.emit('receive', msg);
  	
  				if (msg.id in callbacks) {	
  					callbacks[msg.id](msg.data);
  					delete callbacks[msg.id];			
  					return;
  				}
  				
  				if (msg.event != 'ACK') {
  					client.emit(msg.event, msg.data);
  					send('ACK', {id: msg.id, event: msg.event});
  					return;
  				}
  			});
  		});	
  
  		socket.on('close', () => {
  			setTimeout(connect, opts['reconnect-delay'] * 1000 || 30000, opts);
  			if (client.isConnected) {
  				client.isConnected = false;
  				client.emit('disconnect', opts.id);	
  			}
  			client.isConnected = false;
  		});
  
  		socket.on('error', (err) => client.emit('error', err));		
  	}	
  }
func_code_string: function Client (opts) {
  	this.id = opts.id;
  	this.opts = opts;
  	this.send = send; 
  	this.isConnected = false;
  	let client = this;
  
  	let queue = [];
  	let callbacks = {};
  	let isBusy = true;
  	let socket;
  
  	connect(opts);
  
  	function send (event, data, callback) {
  		if (!client.isConnected && callback)
  			return callback(new Error('CONNECTION'));
  
  		queue.push({event, data, callback});
  		next();
  	}
  
  	function next() {
  		if (isBusy)
  			return;
  		
  		isBusy = true;
  
  		if (queue.length == 0) 
  			return (isBusy = false);
  
  		if (socket) {
  			let msg = {
  				id: genId(),
  				event: queue[0].event, 
  				data: queue[0].data
  			}
  
  			socket.write((!!opts.cipher ? encode(JSON.stringify(msg), opts.cipher, opts.password) : JSON.stringify(msg)) + '|', function (err) {
  				if (err)
  					return socket.emit('error', err);
  
  				if (queue[0].callback)		
  					callbacks[msg.id] = queue[0].callback;
  
  				client.emit('send', queue[0]);
  				queue.shift(); 
  				isBusy = false;
  				next();
  			});
  		}	
  	}
  	
  	function connect (opts) {
  		socket = net.connect({host: opts.host, port: opts.port});
  		queue = [];
  		callbacks = {};
  		isBusy = true;
  
  		socket.on('connect', function () {
  			isBusy = false;
  			client.isConnected = true;
  			client.emit('connect', opts.id);
  		});
  
  		let buffer = '';
  		socket.on('data', function(chunk) {
  			buffer += chunk;
  			let msgs = buffer.split('|');
  			buffer = msgs.pop();
  
  			msgs.forEach(function(packet){
  
  				let msg;
  				try { 
  					msg = JSON.parse(!!opts.cipher ? decode(packet, opts.cipher, opts.password) : packet);
  				} catch(err) { 
  					return socket.emit('error', err);
  				}
  
  				client.emit('receive', msg);
  	
  				if (msg.id in callbacks) {	
  					callbacks[msg.id](msg.data);
  					delete callbacks[msg.id];			
  					return;
  				}
  				
  				if (msg.event != 'ACK') {
  					client.emit(msg.event, msg.data);
  					send('ACK', {id: msg.id, event: msg.event});
  					return;
  				}
  			});
  		});	
  
  		socket.on('close', () => {
  			setTimeout(connect, opts['reconnect-delay'] * 1000 || 30000, opts);
  			if (client.isConnected) {
  				client.isConnected = false;
  				client.emit('disconnect', opts.id);	
  			}
  			client.isConnected = false;
  		});
  
  		socket.on('error', (err) => client.emit('error', err));		
  	}	
  }
func_documentation_string: opts = {host, port, cipher, password}