// Copyright (c) 2020, 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.

/// A trivial embedding of the pub command. Used from tests.
library;

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

import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:pub/pub.dart';
import 'package:pub/src/command.dart';
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/log.dart' as log;
import 'package:pub/src/utils.dart';
import 'package:usage/usage.dart';

final Analytics loggingAnalytics = _LoggingAnalytics();

/// A command for explicitly throwing an exception, to test the handling of
/// unexpected exceptions.
class ThrowingCommand extends PubCommand {
  @override
  String get name => 'fail';

  @override
  String get description => 'Throws an exception';

  bool get hide => true;

  @override
  Future<int> runProtected() async {
    throw StateError('Pub has crashed');
  }
}

/// A command for testing the [ensurePubspecResolved] functionality.
class EnsurePubspecResolvedCommand extends PubCommand {
  @override
  String get name => 'ensure-pubspec-resolved';

  @override
  String get description => 'Resolves pubspec.yaml if needed';

  @override
  bool get hidden => true;

  @override
  Future<int> runProtected() async {
    await ensurePubspecResolved('.');
    return 0;
  }
}

class RunCommand extends Command<int> {
  @override
  String get name => 'run';

  @override
  String get description => 'runs a dart app';

  @override
  Future<int> run() async {
    final executable = await getExecutableForCommand(argResults!.rest.first);
    final packageConfig = executable.packageConfig;
    final process = await Process.start(
      Platform.executable,
      [
        if (packageConfig != null) '--packages=$packageConfig',
        executable.executable,
        ...argResults!.rest.skip(1),
      ],
      mode: ProcessStartMode.inheritStdio,
    );

    return await process.exitCode;
  }
}

class Runner extends CommandRunner<int> {
  late ArgResults _results;

  Runner() : super('pub_command_runner', 'Tests the embeddable pub command.') {
    final analytics = Platform.environment['_PUB_LOG_ANALYTICS'] == 'true'
        ? PubAnalytics(
            () => loggingAnalytics,
            dependencyKindCustomDimensionName: 'cd1',
          )
        : null;
    addCommand(
      pubCommand(
        analytics: analytics,
        isVerbose: () => _results.flag('verbose'),
      )
        ..addSubcommand(ThrowingCommand())
        ..addSubcommand(EnsurePubspecResolvedCommand()),
    );
    addCommand(RunCommand());
    argParser.addFlag('verbose');
  }

  @override
  Future<int> run(Iterable<String> args) async {
    try {
      _results = super.parse(args);
      if (_results.flag('verbose')) {
        log.verbosity = log.Verbosity.all;
      }
      return await runCommand(_results);
    } on UsageException catch (error) {
      log.exception(error);
      return exit_codes.USAGE;
    }
  }

  @override
  Future<int> runCommand(ArgResults topLevelResults) async {
    return await super.runCommand(topLevelResults) ?? 0;
  }
}

Future<void> main(List<String> arguments) async {
  exitCode = await Runner().run(arguments);
}

class _LoggingAnalytics extends AnalyticsMock {
  _LoggingAnalytics() {
    onSend.listen((event) {
      stderr.writeln('[analytics]${json.encode(event)}');
    });
  }

  @override
  bool get firstRun => false;

  @override
  Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
    parameters ??= <String, String>{};
    parameters['viewName'] = viewName;
    return _log('screenView', parameters);
  }

  @override
  Future sendEvent(
    String category,
    String action, {
    String? label,
    int? value,
    Map<String, String>? parameters,
  }) {
    parameters ??= <String, String>{};
    return _log(
      'event',
      {'category': category, 'action': action, 'label': label, 'value': value}
        ..addAll(parameters),
    );
  }

  @override
  Future sendSocial(String network, String action, String target) =>
      _log('social', {'network': network, 'action': action, 'target': target});

  @override
  Future sendTiming(
    String variableName,
    int time, {
    String? category,
    String? label,
  }) {
    return _log('timing', {
      'variableName': variableName,
      'time': time,
      'category': category,
      'label': label,
    });
  }

  Future<void> _log(String hitType, Map message) async {
    final encoded = json.encode({'hitType': hitType, 'message': message});
    stderr.writeln('[analytics]: $encoded');
  }
}
