#!/usr/bin/env node

const path = require('path');
const { spawnSync: _spawnSync, execSync } = require('child_process');
const getOptions = require('../lib/utils/getOptions.js').default;

const { log } = require('../lib/utils/log.js');
const { getCliPath } = require('../lib/servers/getCliPath.js');
const { runPreProcess } = require('../lib/common/runPreProcess.js');
//initPreCommitHook();

const [, , option] = process.argv;
const args = process.argv.slice(3);
const appPath = process.cwd();

const options = getOptions({ start: true, build: true, docs: true }[option]);

function spawnSync(...args) {
  const result = _spawnSync(...args);
  if (result.error) {
    console.error(result.error);
  }
  return result;
}

const { esLint: esLintOptions } = options || {};
const {
  ignoreFilePaths: esLintIgnorePaths,
  fix: esLintFix,
  isCI: isCI,
  reportPath: reportPath
} = esLintOptions || {};

const webpack = getCliPath('webpack');

const nodemon = getCliPath('nodemon');
const babel = getCliPath('babel');
const propertyToJson = getCliPath('propertyToJson');
const esLint = getCliPath('eslint');

runPreProcess({ options, option, nodemon, spawnSync });

let result;
switch (option) {
  case 'lint-setup': {
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/lint/index.js')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  }
  case 'add-lint-scripts': {
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/lint/lintScripts.js')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  }
  case 'postpublish':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/dependencyPostPublish')].concat(args),
      { stdio: 'inherit' }
    );

    process.exit(result.status);
    break;
  case 'rtl':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/rtl')].concat(args),
      { stdio: 'inherit' }
    );

    process.exit(result.status);
    break;
  case 'variableConverter':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/variableConverter')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'selectorReplacer':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/selectorReplacer.js')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'valuereplacer':
    result = spawnSync(
      'node',
      [require.resolve('../lib/common/valueReplacer')].concat(args),
      { stdio: 'inherit' }
    );

    process.exit(result.status);
    break;
  case 'app':
    result = spawnSync(
      'cp',
      ['-r', path.join(__dirname, '..', 'templates', 'app')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'library':
    result = spawnSync(
      'cp',
      ['-r', path.join(__dirname, '..', 'templates', 'library')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'move':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/copy')].concat(args.concat(false)),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'copy':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/copy')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'copyTimezones':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/copyTimezones')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'clone':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/repoClone')].concat(args.concat(args)),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'sslcertupdate':
    result = spawnSync(
      'node',
      [require.resolve('../lib/common/sslcertUpdater')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'propertyToJson':
    result = spawnSync(
      propertyToJson,
      args.map(arg => path.join(appPath, arg)),
      {
        stdio: 'inherit'
      }
    );
    process.exit(result.status);
    break;

  case 'clean':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/clean')].concat(
        args.map(arg => path.join(appPath, arg))
      ),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'devbuild':
    result = spawnSync(
      'node',
      [require.resolve('../lib/servers/devBuild')].concat(args),
      // [require.resolve('../lib/servers/staticServer'), '--expose-http2'].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'nowatchstart':
    result = spawnSync(
      'node',
      [
        require.resolve('../lib/servers/nowatchserver'),
        '--expose-http2'
      ].concat(args),
      // [require.resolve('../lib/servers/staticServer'), '--expose-http2'].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'start':
    result = spawnSync(
      'node',
      [
        options.app.disableWatch
          ? require.resolve('../lib/servers/nowatchserver')
          : require.resolve('../lib/servers/server'),

        '--expose-http2'
      ].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'mockserver':
    result = spawnSync(
      nodemon,
      [
        require.resolve('../lib/servers/mockserver.js'),
        '--delay',
        '2500ms',
        '--watch',
        `${appPath + path.sep}mockapi`
      ].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'docs':
    result = spawnSync(
      'node',
      [require.resolve('../lib/servers/docsServer')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'build':
    result = spawnSync(
      webpack,
      [
        // '--progress',
        // '--profile',
        '--config',
        require.resolve('../lib/configs/webpack.prod.config.js')
      ].concat(args),
      { stdio: 'inherit' }
    );

    // console.log(result);
    process.exit(result.status);
    break;

  case 'build:library:umd':
  case 'build:component:umd':
    result = spawnSync(
      webpack,
      [
        '--config',
        require.resolve('../lib/configs/webpack.component.umd.config.js')
      ],
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'build:css:umd':
    result = spawnSync(
      webpack,
      ['--config', require.resolve('../lib/configs/webpack.css.umd.config.js')],
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;
  case 'build:component:server':
    result = spawnSync(
      webpack,
      ['--config', require.resolve('../lib/configs/webpack.server.config.js')],
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'build:library:cmjs':
  case 'build:component:cmjs':
    result = spawnSync(
      babel,
      [
        'src',
        '-d',
        'lib',
        `--presets=${require.resolve('../lib/babel/cmjs-plugins-presets.js')}`,
        '--copy-files'
      ].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'build:library:es':
  case 'build:component:es':
    result = spawnSync(
      babel,
      [
        'src',
        '--out-dir',
        'es',
        `--presets=${require.resolve('../lib/babel/es-plugins-presets.js')}`,
        '--copy-files'
      ].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'test':
    result = spawnSync(
      'node',
      [require.resolve('../lib/jest/run.js')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'sstest':
    result = spawnSync(
      'node',
      [require.resolve('../lib/servers/scrServer')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'impact:library':
    result = spawnSync(
      webpack,
      [
        '--config',
        require.resolve('../lib/configs/webpack.impact.config.js')
      ].concat(args),
      { stdio: 'inherit' }
    );

    // result = spawnSync(
    //   webpack,
    //   [require.resolve('../lib/server/libraryImpact')].concat(args),
    //   { stdio: 'inherit' }
    // )

    process.exit(result.status);
    break;

  case 'publish:report':
    result = spawnSync(
      'sh',
      [path.join(__dirname, '..', 'lib', 'sh', 'reportPublish.sh')].concat(
        args
      ),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'impact':
    result = spawnSync(
      'node',
      [require.resolve('../lib/server/impactServer')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'cluster:monitor':
    result = spawnSync(
      'node',
      [require.resolve('../lib/servers/clusterHubServer')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'lint':
    result = spawnSync(
      esLint,
      [
        '-c',
        path.join(__dirname, '..', '.eslintrc.js'),
        isCI ? '--no-eslintrc' : false,
        '--ignore-path',
        esLintIgnorePaths
          ? path.join(appPath, esLintIgnorePaths)
          : path.join(__dirname, '..', '.eslintignore'),
        esLintFix ? '--fix' : false,
        isCI ? '-f' : false,
        isCI ? path.join(__dirname, './../lib/utils/lintReporter.js') : false
      ]
        .filter(Boolean)
        .concat(args.map(arg => path.join(appPath, arg))),
      {
        stdio: 'inherit'
      }
    );
    isCI ? log(`You can see the eslint result from ${reportPath}`) : false;
    break;

  case 'set:config':
    result = spawnSync(
      'node',
      [require.resolve('../lib/utils/setEnvVariables')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case 'help':
    result = spawnSync(
      'node',
      [require.resolve('../lib/servers/helpServer')].concat(args),
      { stdio: 'inherit' }
    );
    process.exit(result.status);
    break;

  case '--version':
  case '-version':
  case '--v':
  case '-v':
    log(`@zohodesk/react-cli v${require('../package.json').version}`);
    log(`Node Js Version : ${process.version}`);
    log(`Npm Version : ${execSync('npm --version')}`);
    break;
  default:
    log(`react-cli > Unknown option "${option}"`);
    log('react-cli app <appName>');
    log('react-cli library <libraryName>');
    log('react-cli start');
    log('react-cli build');
    log('react-cli sstest');
    log('react-cli test');
    log('react-cli publish:report');
    log('react-cli build:library:es');
    log('react-cli gitclone <last argument clone folder>');
    log('react-cli hgclone <last argument clone folder>');

    process.exit(0);
    break;
}
