text: const config = require('./vue/dist/UIconfig');
  
  const Koa = require('koa');
  const serve = require('koa-static');
  const _ = require('lodash');
  
  const opn = require('opn');
  const server = require('http').createServer();
  const router = require('koa-router')();
  const ws = require('ws');
  const app = new Koa();
  const koaBody = require('koa-body');
  
  const WebSocketServer = require('ws').Server;
  const wss = new WebSocketServer({ server: server });
  
  const cache = require('./state/cache');
  
  const nodeCommand = _.last(process.argv[1].split('/'));
  const isDevServer = nodeCommand === 'server' || nodeCommand === 'server.js';
  
  wss.on('connection', ws => {
    ws.isAlive = true;
    ws.on('pong', () => {
      ws.isAlive = true;
    });
    ws.ping(_.noop);
    ws.on('error', e => {
      console.error(new Date, '[WS] connection error:', e);
    });
  });
  
  
  setInterval(() => {
    wss.clients.forEach(ws => {
      if(!ws.isAlive) {
        console.log(new Date, '[WS] stale websocket client, terminiating..');
        return ws.terminate();
      }
  
      ws.isAlive = false;
      ws.ping(_.noop);
    });
  }, 10 * 1000);
  
  // broadcast function
  const broadcast = data => {
    if(_.isEmpty(data)) {
      return;
    }
  
    const payload = JSON.stringify(data);
  
    wss.clients.forEach(ws => {
      ws.send(payload, err => {
        if(err) {
          console.log(new Date, '[WS] unable to send data to client:', err);
        }
      });
    }
    );
  }
  cache.set('broadcast', broadcast);
  
  
  const ListManager = require('./state/listManager');
  const GekkoManager = require('./state/gekkoManager');
  
  // initialize lists and dump into cache
  cache.set('imports', new ListManager);
  cache.set('gekkos', new GekkoManager);
  cache.set('apiKeyManager', require('./apiKeyManager'));
  
  // setup API routes
  
  const WEBROOT = __dirname + '/';
  const ROUTE = n => WEBROOT + 'routes/' + n;
  
  // attach routes
  const apiKeys = require(ROUTE('apiKeys'));
  router.get('/api/info', require(ROUTE('info')));
  router.get('/api/strategies', require(ROUTE('strategies')));
  router.get('/api/configPart/:part', require(ROUTE('configPart')));
  router.get('/api/apiKeys', apiKeys.get);
  
  const listWraper = require(ROUTE('list'));
  router.get('/api/imports', listWraper('imports'));
  router.get('/api/gekkos', listWraper('gekkos'));
  router.get('/api/exchanges/portfolios', require(ROUTE('portfolios')));
  router.get('/api/exchanges', require(ROUTE('exchanges')));
  
  router.post('/api/addApiKey', koaBody({ multipart: true }), apiKeys.add);
  router.post('/api/removeApiKey', koaBody({ multipart: true }), apiKeys.remove);
  router.post('/api/scan', koaBody({ multipart: true }), require(ROUTE('scanDateRange')));
  router.post('/api/scansets', koaBody({ multipart: true }), require(ROUTE('scanDatasets')));
  router.post('/api/backtest', koaBody({ multipart: true }), require(ROUTE('backtest')));
  router.post('/api/import', koaBody({ multipart: true }), require(ROUTE('import')));
  router.post('/api/startGekko', koaBody({ multipart: true }), require(ROUTE('startGekko')));
  router.post('/api/stopGekko', koaBody({ multipart: true }), require(ROUTE('stopGekko')));
  router.post('/api/deleteGekko', koaBody({ multipart: true }), require(ROUTE('deleteGekko')));
  router.post('/api/getCandles', koaBody({ multipart: true }), require(ROUTE('getCandles')));
  
  
  // incoming WS:
  // wss.on('connection', ws => {
  //   ws.on('message', _.noop);
  // });
  
  
  app
    .use(require('koa2-cors')())
    .use(serve(WEBROOT + 'vue/dist'))
    .use(require('koa-logger')())
    .use(router.routes())
    .use(router.allowedMethods());
  
  server.timeout = config.api.timeout || 120000;
  server.on('request', app.callback());
  server.listen(config.api.port, config.api.host, '::', () => {
    const host = `${config.ui.host}:${config.ui.port}${config.ui.path}`;
  
    if(config.ui.ssl) {
      var location = `https://${host}`;
    } else {
      var location = `http://${host}`;
    }
  
    console.log('Serving Gekko UI on ' + location +  '\n');
  
  
    // only open a browser when running `node gekko`
    // this prevents opening the browser during development
    if(!isDevServer && !config.headless) {
      opn(location)
        .catch(err => {
          console.log('Something went wrong when trying to open your web browser. UI is running on ' + location + '.');
        });
    }
  });
  