#!/usr/bin/env node

'use strict'
const program = require('commander'),
  color = require('colorful'),
  packageInfo = require('../package.json'),
  ruleLoader = require('../lib/ruleLoader'),
  util = require('../lib/util'),
  logUtil = require('../lib/log');

program
  .version(packageInfo.version)
  .option('-p, --port [value]', 'proxy port, 8001 for default')
  .option('-w, --web [value]', 'web GUI port, 8002 for default')
  .option('-r, --rule [value]', 'path for rule file,')
  .option('-l, --throttle [value]', 'throttle speed in kb/s (kbyte / sec)')
  .option('-i, --intercept', 'intercept(decrypt) https requests when root CA exists')
  .option('-s, --silent', 'do not print anything into terminal')
  .option('-c, --clear', 'clear all the certificates and temp files')
  .option('--ignore-unauthorized-ssl', 'ignore all ssl error')
  .parse(process.argv);

if (program.clear) {
  require('../lib/certMgr').clearCerts(() => {
    util.deleteFolderContentsRecursive(util.getAnyProxyPath('cache'));
    console.log(color.green('done !'));
    process.exit(0);
  });
} else if (program.root) {
  require('../lib/certMgr').generateRootCA(() => {
    process.exit(0);
  });
} else {
  const AnyProxy = require('../proxy.js');
  let proxyServer;

  if (program.silent) {
    logUtil.setPrintStatus(false);
  }

  // load rule module
  new Promise((resolve, reject) => {
    if (program.rule) {
      resolve(ruleLoader.requireModule(program.rule));
    } else {
      resolve(null);
    }
  })
  .catch(e => {
    logUtil.printLog('Failed to load rule file', logUtil.T_ERR);
    logUtil.printLog(e, logUtil.T_ERR);
    process.exit();
  })

  //start proxy
  .then(ruleModule => {
    proxyServer = new AnyProxy.ProxyServer({
      type: 'http',
      port: program.port || 8001,
      throttle: program.throttle,
      rule: ruleModule,
      webInterface: {
        enable: true,
        webPort: program.web,
      },        
      forceProxyHttps: program.intercept,
      dangerouslyIgnoreUnauthorized: !!program.ignoreUnauthorizedSsl,
      silent: program.silent
    });
    // proxyServer.on('ready', () => {});
    proxyServer.start();
  })
  .catch(e => {
    logUtil.printLog(e, logUtil.T_ERR);
    if (e && e.code) {
      logUtil.printLog('code ' + e.code, logUtil.T_ERR);
    }
    logUtil.printLog(e.stack, logUtil.T_ERR);
  });

  process.on('exit', (code) => {
    if (code > 0) {
      logUtil.printLog('AnyProxy is about to exit with code: ' + code, logUtil.T_ERR);
    }

    process.exit();
  });

  //exit cause ctrl+c
  process.on('SIGINT', () => {
    try {
      proxyServer && proxyServer.close();
    } catch (e) {
      console.error(e);
    }
    process.exit();
  });

  process.on('uncaughtException', (err) => {
    let errorTipText = 'got an uncaught exception, is there anything goes wrong in your rule file ?\n';
    try {
      if (err && err.stack) {
        errorTipText += err.stack;
      } else {
        errorTipText += err;
      }
    } catch (e) {}
    logUtil.printLog(errorTipText, logUtil.T_ERR);
    try {
      proxyServer && proxyServer.close();        
    } catch (e) {}
    process.exit();
  });
}
