/**
 **      ==============================
 **       O           O      O   OOOO
 **       O           O     O O  O   O
 **       O           O     O O  O   O
 **       OOOO   OOOO O     OOO  OOOO
 **       O   O       O    O   O O   O
 **       O   O       O    O   O O   O
 **       OOOO        OOOO O   O OOOO
 **      ==============================
 **      Dr. Stefan Bosse http://www.bsslab.de
 **
 **      COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
 **                 BY THE AUTHOR(S).
 **                 THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
 **                 MODIFIED, OR OTHERWISE USED IN A CONTEXT
 **                 OUTSIDE OF THE SOFTWARE SYSTEM.
 **
 **    $AUTHORS:     Stefan Bosse
 **    $INITIAL:     (C) 2006-2025 bLAB
 **    $CREATED:     1-3-18 by sbosse.
 **    $VERSION:     1.3.1
 **
 **    $INFO:
 **
 **  JAM Shell Interpreter (Front end)
 **
 **    $ENDOFINFO
 */
/* Soem hacks */
process.noDeprecation = true

var Comp = Require('com/compat');
var Io = Require('com/io');
var doc = Require('doc/doc');
var table = Require('doc/table');
var readline = Require('com/readline');
var readlineSync = Require('term/readlineSync');
var renderer = doc.Renderer({lazy:true});
var http = Require('http');
var httpserv = Require('http/https');  // a file server!
try { var https = require('https'); } catch (e) {}; if (!https.request) https=undefined;
var geoip = Require('geoip/geoip');  // a geo location database server 
var util = Require('util')
var sip = Require('top/rendezvous');
var db = Require('db/db');
// JAM Shell Interpreter (Back end)
var JamShell = Require('shell/shell');

var nlp = Require('nlp/nlp');

var ml    = Require('ml/ml')
var nn    = Require('nn/nn')
var csp   = Require('csp/csp')
var sat   = Require('logic/sat')
var logic = Require('logic/prolog')
var csv   = Require('parser/papaparse');
var ampCOM = Require('jam/ampCOM');
var numerics = Require('numerics/numerics')
var osutils = Require('os/osutils');
var UI    = Require('ui/app/app');
var Des48 = Require('dos/des48');

var p;

var options= {
  args:[],
  echo: true,
  modules : {
    csp : csp,
    csv : csv,
    db : db,
    des48 : Des48,
    doc : doc,
    geoip : geoip,
    http : http,
    httpserv : httpserv,
    https : https,
    logic:logic,
    ml:ml,
    nlp:nlp,
    nn:nn,
    numerics:numerics,
    os:osutils,
    readline : readline,
    readlineSync : readlineSync,
    sat : sat,
    sip : sip,
    table : table,
    UI: UI,
  },
  extensions : {
    url2addr: ampCOM.url2addr,
    sleep: process.watchdog&&process.watchdog.sleep?
      function (milli) {
        process.watchdog.sleep(milli)
      }:undefined
  },
  nameopts : {length:8, memorable:true, lowercase:true},
  Nameopts : {length:8, memorable:true, uppercase:true},
  output : null,
  // AMP network ports, JAM interconnect
  // <ipport>|http:<ipport>|https:<ipport>|IP:<ipport>|NORTH:<ipport>|...
  // <=> port(DIR.IP(9901),{proto:'http'})
  links  :  [],
  ports  :  [], 
  renderer : renderer,
  server : false,
  verbose : 0
}

process.on('uncaughtException', function (err) {
  console.error(err.stack);
  console.log("jamsh not exiting...");
});

if ((p=process.argv.indexOf('--'))>0) {
  options.args=process.argv.slice(p+1,process.argv.length);
  process.argv=process.argv.slice(0,p);
}

// return {port:DIR.IP(9901),options:{proto:'http'}}
// input. <ipport>|http:<ipport>|https:<ipport>|IP:<ipport>|NORTH:<ipport>|...
function parsePort(str) {
  var tokens = str.split(':'),
      ipproto = 'http',
      ipaddr = '',
      ampport = 'IP',
      ipport = 9999
  for(var i=0;i<tokens.length;i++) {
    if (['http','https','udp','tcp'].indexOf(tokens[i])!=-1) ipproto=tokens[i];
    else if (/^\/\//.test(tokens[i])) ipaddr=tokens[i].replace('//','');
    else if (!isNaN(Number(tokens[i]))) ipport=Number(tokens[i]);
    else if (tokens[i]=='*') ipport=tokens[1];
    else if (['IP','NORTH','SOUTH','WEST','EAST','UP','DOWN'].indexOf(tokens[i])!=-1) ampport=tokens[i];
    else throw ("parsePort: Invalid port parameter "+str)
  }
  return {
    port:DIR[ampport](ipaddr?ipaddr+':'+ipport:ipport),
    options:{
      proto:ipproto
    }
  }
}

if (process.argv[1].match(/jamsh$/)||process.argv[1].match(/jamsh\.debug$/)) { try {
  var ind;
  if (process.argv.indexOf('-h')>0) {
    print('usage: jamsh [-v(erbose)]')
    print('       [-i(nteractive mode)]')
    print('       [-s(erver mode)]')
    print('       [-p(ort) <url>]')
    print('       [-l(inkto) <url>]')    
    print('       [javascript script file]')
    print('       [-e(xecute) "shell command"]')
    print('JAM network port url scheme:')
    print('  (AMP endpoint, defaults are DIR.IP(9999), ipproto:http)')
    print('  <ipproto>://<hostip|hostname>:<ipport>,  <ipproto>=http|https|udp|tcp')
    print('  <ipproto>://<hostip|hostname>:<ipport>?secure=<securitykey>' )
    print('  <ipport>|<ipproto>:<ipport> // localhost')
    print('  NORTH|SOUTH|WEST|EAST|...');
    print('Examples:');
    print('  --- HTTP client connection to remote jamsh service endpoint ---');
    print('  jamsh -v -p http://localhost:* -l http://edu-9.de:20101?secure=DD:DD:DD:DD -s');
    return;
  }
  var skip=0
  process.argv.forEach(function (arg,argi) { 
    if (argi<2) return;
    if (skip) return skip--;
    switch (arg) {
      case '-v': options.verbose++; break; 
      case '-s': options.output=console.log; options.server=true; break;
      case '-i': options.server=false; break;
      case '-e': 
        options.server=true;
        options.output=console.log;
        options.exec=process.argv[argi+1];
        skip++;
        break;
      case '-p': options.ports.push(parsePort(process.argv[argi+1])); skip++; break;
      case '-l': options.links.push(process.argv[argi+1]); skip++; break;
      default:
        if (arg[0]!='-') {
          // script
          options.script=arg;
          options.output=console.log;
          options.server=true;
        } else throw ("Invalid command line argument "+arg)
    }
  })
  if (!options.server && options.verbose==0) options.verbose=1; 
  JamShell(options).init();
} catch (e) { print(e.toString()) }}
