// 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.
void main(List<String> rawArgs) {
  var logger = Logger('Performance Measurement Client');
  logger.onRecord.listen((LogRecord rec) {
    print(rec.message);
  });
  var args = parseArgs(rawArgs);

  var driver = Driver(diagnosticPort: args.diagnosticPort);
  var stream = openInput(args);
  late StreamSubscription<Operation?> subscription;
  subscription = stream.listen((Operation? op) {
    var 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 = Duration(seconds: 25);

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

final ArgParser argParser = () {
  var argParser = 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 = Logger('openInput');
  Stream<List<int>> inputRaw;
  if (args.inputPath == 'stdin') {
    inputRaw = stdin;
  } else {
    inputRaw = File(args.inputPath).openRead();
  }
  for (var 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
      .cast<List<int>>()
      .transform(systemEncoding.decoder)
      .transform(LineSplitter())
      .transform(InputConverter(args.tmpSrcDirPath, args.srcPathMap));
}

/// Parse the command line arguments.
PerfArgs parseArgs(List<String> rawArgs) {
  ArgResults args;
  var perfArgs = PerfArgs();
  try {
    args = argParser.parse(rawArgs);
  } on Exception catch (e) {
    print(e);
    printHelp();
    exit(1);
  }
  var helpArg = args[HELP_CMDLINE_OPTION] as bool;
  var showHelp = helpArg || args.rest.isNotEmpty;

  var inputArg = args[INPUT_CMDLINE_OPTION];
  if (inputArg is! String || inputArg.isEmpty) {
    print('missing $INPUT_CMDLINE_OPTION argument');
    showHelp = true;
  } else {
    perfArgs.inputPath = inputArg;
  }

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

  var tmpSrcDirPathArg = args[TMP_SRC_DIR_OPTION];
  if (tmpSrcDirPathArg is! String || tmpSrcDirPathArg.isEmpty) {
    print('missing $TMP_SRC_DIR_OPTION argument');
    showHelp = true;
  } else {
    perfArgs.tmpSrcDirPath = _withTrailingSeparator(tmpSrcDirPathArg);
  }

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

  var verboseArg = args[VERY_VERBOSE_CMDLINE_OPTION] as bool;
  if (verboseArg || rawArgs.contains('-vv')) {
    Logger.root.level = Level.FINE;
  } else if (verboseArg) {
    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.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.
  late 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 = PathMap();

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

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