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

/// This executable provides the ability to run the migration tool in process
/// on a single package.  It should be invoked with two command-line arguments:
/// a path to a configuration file and the name of a package to migrate.
///
/// The configuration file format is a JSON map, with the following keys:
/// - `sdk_root`: path to the SDK source code on the user's machine (this is the
///   directory that contains `pkg`, `third_party`, `tests`, etc.
/// - `output_root`: if present, path to the directory on the user's machine
///   where output HTML files should go.  A subdirectory will be created for
///   each package that is migrated.
/// - `external_packages`: a map (name => path) of additional non-SDK packages
///   that may need to be migrated.
/// - `port`: if present, the port where a server should be spawned serving HTML
///   pages.
library migration_runner;

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

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';

Future<void> main(List<String> args) async {
  if (args.length != 2) {
    throw StateError(
        'Exactly two arguments are required: the path to a JSON configuration '
        'file, and the name of the package to migrate');
  }
  var testInfoJsonPath = args[0];
  var testInfoJson = json.decode(io.File(testInfoJsonPath).readAsStringSync());
  var packageName = args[1];
  var testInfo = TestInfo(testInfoJson);
  var packageRoot = testInfo.packageRoot(packageName);
  var port = testInfo.port;
  print('Preparing to migrate');
  var migrationTest = MigrationTest();
  migrationTest.setUp();
  print('Migrating');
  await migrationTest.run(packageRoot, port);
  if (port == null) {
    print('Done');
    io.exit(0);
  } else {
    print('Done.  Please point your browser to localhost:$port/\$filePath');
  }
}

class MigrationBase {
  ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
  MockServerChannel serverChannel;
  AnalysisServer server;

  AnalysisServer createAnalysisServer() {
    //
    // Create server
    //
    var options = AnalysisServerOptions();
    var sdkPath = FolderBasedDartSdk.defaultSdkDirectory(
      PhysicalResourceProvider.INSTANCE,
    ).path;
    return AnalysisServer(
        serverChannel,
        resourceProvider,
        options,
        DartSdkManager(sdkPath),
        CrashReportingAttachmentsBuilder.empty,
        InstrumentationService.NULL_SERVICE);
  }

  void processNotification(Notification notification) {
    if (notification.event == SERVER_NOTIFICATION_ERROR) {
      fail('${notification.toJson()}');
    }
  }

  Future<Response> sendAnalysisSetAnalysisRoots(List<String> directories) {
    var request =
        AnalysisSetAnalysisRootsParams(directories, []).toRequest('0');
    return waitResponse(request);
  }

  Future<Response> sendEditDartfix(List<String> directories, int port) {
    var request = EditDartfixParams(directories,
            includedFixes: ['non-nullable'], port: port)
        .toRequest('1');
    return waitResponse(request);
  }

  void setUp() {
    serverChannel = MockServerChannel();
    server = createAnalysisServer();
    server.pluginManager = TestPluginManager();
    // listen for notifications
    var notificationStream = serverChannel.notificationController.stream;
    notificationStream.listen((Notification notification) {
      processNotification(notification);
    });
  }

  void tearDown() {
    server.done();
    server = null;
    serverChannel = null;
  }

  /// Returns a [Future] that completes when the server's analysis is complete.
  Future waitForTasksFinished() {
    return server.onAnalysisComplete;
  }

  /// Completes with a successful [Response] for the given [request].
  Future<Response> waitResponse(Request request,
      {bool throwOnError = true}) async {
    return serverChannel.sendRequest(request, throwOnError: throwOnError);
  }
}

class MigrationTest extends MigrationBase {
  Future<void> run(String packageRoot, int port) async {
    var packageRoots = <String>[packageRoot];
    await sendAnalysisSetAnalysisRoots(packageRoots);
    await sendEditDartfix(packageRoots, port);
  }
}

class TestInfo {
  static const Set<String> thirdPartyPackages = {
    'charcode',
    'collection',
    'logging',
    'meta',
    'pedantic',
    'typed_data'
  };

  static const Set<String> builtInPackages = {'meta', 'path'};

  final Map<String, Object> testInfoJson;

  TestInfo(this.testInfoJson);

  Map<String, String> get externalPackages =>
      ((testInfoJson['external_packages'] ?? {}) as Map).cast<String, String>();

  String get outputRoot => testInfoJson['output_root'];

  int get port => testInfoJson['port'];

  String get sdkRoot => testInfoJson['sdk_root'];

  String packageRoot(String packageName) {
    if (thirdPartyPackages.contains(packageName)) {
      return path.join(sdkRoot, 'third_party', 'pkg', packageName);
    } else if (builtInPackages.contains(packageName)) {
      return path.join(sdkRoot, 'pkg', packageName);
    } else if (externalPackages.containsKey(packageName)) {
      return externalPackages[packageName];
    } else {
      throw StateError('Unrecognized package $packageName');
    }
  }
}
