// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;

import 'driver.dart';
import 'input_converter.dart';
import 'operation.dart';

/**
 * Launch and interact with the analysis server.
 */
main(List<String> rawArgs) {
  Logger logger = new Logger('Performance Measurement Client');
  logger.onRecord.listen((LogRecord rec) {
    print(rec.message);
  });
  PerfArgs args = parseArgs(rawArgs);

  Driver driver = new Driver(diagnosticPort: args.diagnosticPort);
  Stream<Operation> stream = openInput(args);
  StreamSubscription<Operation> subscription;
  subscription = stream.listen((Operation op) {
    Future future = driver.perform(op);
    if (future != null) {
      logger.log(Level.FINE, 'pausing operations for ${op.runtimeType}');
      subscription.pause(future.then((_) {
        logger.log(Level.FINE, 'resuming operations');
      }));
    }
  }, onDone: () {
    subscription.cancel();
    driver.stopServer(SHUTDOWN_TIMEOUT);
  }, onError: (e, s) {
    subscription.cancel();
    logger.log(Level.SEVERE, '$e\n$s');
    driver.stopServer(SHUTDOWN_TIMEOUT);
  });
  driver.runComplete.then((Results results) {
    results.printResults();
  }).whenComplete(() {
    return subscription.cancel();
  });
}

const DIAGNOSTIC_PORT_OPTION = 'diagnosticPort';
const HELP_CMDLINE_OPTION = 'help';
const INPUT_CMDLINE_OPTION = 'input';
const MAP_OPTION = 'map';

/**
 * The amount of time to give the server to respond to a shutdown request
 * before forcibly terminating it.
 */
const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 25);

const TMP_SRC_DIR_OPTION = 'tmpSrcDir';
const VERBOSE_CMDLINE_OPTION = 'verbose';
const VERY_VERBOSE_CMDLINE_OPTION = 'vv';

ArgParser _argParser;

ArgParser get argParser {
  _argParser = new ArgParser();

  _argParser.addOption(INPUT_CMDLINE_OPTION,
      abbr: 'i',
      help: '<filePath>\n'
          'The input file specifying how this client should interact with the server.\n'
          'If the input file name is "stdin", then the instructions are read from standard input.');
  _argParser.addMultiOption(MAP_OPTION,
      abbr: 'm',
      splitCommas: false,
      help: '<oldSrcPath>,<newSrcPath>\n'
          'This option defines a mapping from the original source directory <oldSrcPath>\n'
          'when the instrumentation or log file was generated\n'
          'to the target source directory <newSrcPath> used during performance testing.\n'
          'Multiple mappings can be specified.\n'
          'WARNING: The contents of the target directory will be modified');
  _argParser.addOption(TMP_SRC_DIR_OPTION,
      abbr: 't',
      help: '<dirPath>\n'
          'The temporary directory containing source used during performance measurement.\n'
          'WARNING: The contents of the target directory will be modified');
  _argParser.addOption(DIAGNOSTIC_PORT_OPTION,
      abbr: 'd',
      help: 'localhost port on which server will provide diagnostic web pages');
  _argParser.addFlag(VERBOSE_CMDLINE_OPTION,
      abbr: 'v', help: 'Verbose logging', negatable: false);
  _argParser.addFlag(VERY_VERBOSE_CMDLINE_OPTION,
      help: 'Extra verbose logging', negatable: false);
  _argParser.addFlag(HELP_CMDLINE_OPTION,
      abbr: 'h', help: 'Print this help information', negatable: false);
  return _argParser;
}

/**
 * Open and return the input stream specifying how this client
 * should interact with the analysis server.
 */
Stream<Operation> openInput(PerfArgs args) {
  var logger = new Logger('openInput');
  Stream<List<int>> inputRaw;
  if (args.inputPath == 'stdin') {
    inputRaw = stdin;
  } else {
    inputRaw = new File(args.inputPath).openRead();
  }
  for (PathMapEntry entry in args.srcPathMap.entries) {
    logger.log(
        Level.INFO,
        'mapping source path\n'
        '  from ${entry.oldSrcPrefix}\n  to   ${entry.newSrcPrefix}');
  }
  logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}');
  return inputRaw
      .transform(systemEncoding.decoder)
      .transform(new LineSplitter())
      .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap));
}

/**
 * Parse the command line arguments.
 */
PerfArgs parseArgs(List<String> rawArgs) {
  ArgResults args;
  PerfArgs perfArgs = new PerfArgs();
  try {
    args = argParser.parse(rawArgs);
  } on Exception catch (e) {
    print(e);
    printHelp();
    exit(1);
  }

  bool showHelp = args[HELP_CMDLINE_OPTION] || args.rest.isNotEmpty;

  bool isMissing(key) => args[key] == null || args[key].isEmpty;

  perfArgs.inputPath = args[INPUT_CMDLINE_OPTION];
  if (isMissing(INPUT_CMDLINE_OPTION)) {
    print('missing $INPUT_CMDLINE_OPTION argument');
    showHelp = true;
  }

  for (String pair in args[MAP_OPTION]) {
    if (pair is String) {
      int index = pair.indexOf(',');
      if (index != -1 && pair.indexOf(',', index + 1) == -1) {
        String oldSrcPrefix = _withTrailingSeparator(pair.substring(0, index));
        String newSrcPrefix = _withTrailingSeparator(pair.substring(index + 1));
        if (new Directory(newSrcPrefix).existsSync()) {
          perfArgs.srcPathMap.add(oldSrcPrefix, newSrcPrefix);
          continue;
        }
      }
    }
    print('must specifiy $MAP_OPTION <oldSrcPath>,<newSrcPath>');
    showHelp = true;
  }

  perfArgs.tmpSrcDirPath = _withTrailingSeparator(args[TMP_SRC_DIR_OPTION]);
  if (isMissing(TMP_SRC_DIR_OPTION)) {
    print('missing $TMP_SRC_DIR_OPTION argument');
    showHelp = true;
  }

  String portText = args[DIAGNOSTIC_PORT_OPTION];
  if (portText != null) {
    if (int.tryParse(portText) == null) {
      print('invalid $DIAGNOSTIC_PORT_OPTION: $portText');
      showHelp = true;
    } else {
      perfArgs.diagnosticPort = int.tryParse(portText);
    }
  }

  if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) {
    Logger.root.level = Level.FINE;
  } else if (args[VERBOSE_CMDLINE_OPTION]) {
    Logger.root.level = Level.INFO;
  } else {
    Logger.root.level = Level.WARNING;
  }

  if (showHelp) {
    printHelp();
    exit(1);
  }

  return perfArgs;
}

void printHelp() {
  print('');
  print('Launch and interact with the AnalysisServer');
  print('');
  print(argParser.usage);
}

/**
 * Ensure that the given path has a trailing separator
 */
String _withTrailingSeparator(String dirPath) {
  if (dirPath != null && dirPath.length > 4) {
    if (!dirPath.endsWith(path.separator)) {
      return '$dirPath${path.separator}';
    }
  }
  return dirPath;
}

/**
 * The performance measurement arguments specified on the command line.
 */
class PerfArgs {
  /**
   * The file path of the instrumentation or log file
   * used to drive performance measurement,
   * or 'stdin' if this information should be read from standard input.
   */
  String inputPath;

  /**
   * A mapping from the original source directory
   * when the instrumentation or log file was generated
   * to the target source directory used during performance testing.
   */
  final PathMap srcPathMap = new PathMap();

  /**
   * The temporary directory containing source used during performance measurement.
   */
  String tmpSrcDirPath;

  /**
   * The diagnostic port for Analysis Server or `null` if none.
   */
  int diagnosticPort;
}
