/* jslint node: true */
'use strict';

//	enigma-bbs
const MenuModule	= require('../core/menu_module.js').MenuModule;
const resetScreen	= require('../core/ansi_term.js').resetScreen;

//	deps
const async			= require('async');
const _				= require('lodash');
const SSHClient		= require('ssh2').Client;

exports.getModule	= DoorPartyModule;

exports.moduleInfo = {
	name	: 'DoorParty',
	desc	: 'DoorParty Access Module',
	author	: 'NuSkooler',
};


function DoorPartyModule(options) {
	MenuModule.call(this, options);
	
	const self	= this;
	
	//	establish defaults
	this.config	= options.menuConfig.config;
	this.config.host		= this.config.host || 'dp.throwbackbbs.com';
	this.config.sshPort 	= this.config.sshPort || 22;
	this.config.rloginPort	= this.config.rloginPort || 513;	
	
	this.initSequence = function() {
		let clientTerminated;
		
		async.series(
			[
				function validateConfig(callback) {
					if(!_.isString(self.config.username)) {
						return callback(new Error('Config requires "username"!'));
					}
					if(!_.isString(self.config.password)) {
						return callback(new Error('Config requires "password"!'));
					}
					if(!_.isString(self.config.bbsTag)) {
						return callback(new Error('Config requires "bbsTag"!'));
					}
					return callback(null);
				},
				function establishSecureConnection(callback) {
					self.client.term.write(resetScreen());
					self.client.term.write('Connecting to DoorParty, please wait...\n');
									
					const sshClient = new SSHClient();
					
					let pipeRestored = false;
					let pipedStream;
					const restorePipe = function() {
						if(pipedStream && !pipeRestored && !clientTerminated) {
							self.client.term.output.unpipe(pipedStream);						
							self.client.term.output.resume();
						}	
					};										
					
					sshClient.on('ready', () => {
						//	track client termination so we can clean up early
						self.client.once('end', () => {
							self.client.log.info('Connection ended. Terminating DoorParty connection');
							clientTerminated = true;
							sshClient.end();							
						});
						
						//	establish tunnel for rlogin
						sshClient.forwardOut('127.0.0.1', self.config.sshPort, self.config.host, self.config.rloginPort, (err, stream) => {
							if(err) {
								return callback(new Error('Failed to establish tunnel'));
							}

							//
							//	Send rlogin
							//	DoorParty wants the "server username" portion to be in the format of [BBS_TAG]USERNAME, e.g.
							//	[XA]nuskooler
							//
							const rlogin = `\x00${self.client.user.username}\x00[${self.config.bbsTag}]${self.client.user.username}\x00${self.client.term.termType}\x00`; 
							stream.write(rlogin);
							
							pipedStream = stream;	//	:TODO: this is hacky...
							self.client.term.output.pipe(stream);
							
							stream.on('data', d => {
								//	:TODO: we should just pipe this...
								self.client.term.rawWrite(d);
							});
							
							stream.on('close', () => {
								restorePipe();
								sshClient.end();
							});
						});
					});
					
					sshClient.on('close', () => {
						restorePipe();
						callback(null);
					});
										
					sshClient.connect( {
						host 		: self.config.host,
						port		: self.config.sshPort,
						username	: self.config.username,
						password	: self.config.password,
					});
					
					//	note: no explicit callback() until we're finished!
				}		
			],
			err => {
				if(err) {
					self.client.log.warn( { error : err.toString() }, 'DoorParty error');
				}
				
				//	if the client is stil here, go to previous
				if(!clientTerminated) {
					self.prevMenu();
				}
			}
		);
	};
	
}

require('util').inherits(DoorPartyModule, MenuModule);
@@ -709,16 +709,18 @@
 Port %7C%7C 
+20
 22;%0A%09thi

Change default SSH port