// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8

// TODO(https://fxbug.dev/84961): Fix null safety and remove this language version.
// @dart=2.9

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

import 'package:args/args.dart';
import 'package:collection/collection.dart';
import 'package:dart_strict_deps_lib/dependency_check.dart' as dependency_check;
import 'package:dart_strict_deps_lib/file_processor.dart' as file_processor;
import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
import 'package:tools.dart-strict-deps.dart_strict_deps_proto/protos/models.pb.dart';

p.Context context = p.Context(style: p.Style.posix);

/// Writes serialized TargetCheckResult to file
void writeOutfile(String file, TargetCheckResult checkResult) {
  File(file).writeAsString(jsonEncode(checkResult.toProto3Json()));
}

// Returns string [s] with [indents] number of spaces in front.
String indentedString(String s, {@required int indents}) {
  return s.padLeft(s.length + indents, ' ');
}

/// Represents a flattened out structure for the parsed data.
///
/// This is used for easier formatting of output.
class FlatResult {
  // File path of the importing file
  final String filePath;
  // Import statement being represented
  final ImportResult importResult;
  // Whether the package of import has been imported or not
  final bool knownPackage;
  FlatResult(this.filePath, this.importResult, {this.knownPackage});
}

/// Prints file level warnings to stdout.
void printFileWarnings(String fileName, List<FlatResult> flatResults) {
  final fileState = flatResults[0].importResult.state;
  if (fileState == ImportResult_State.MISSING_FROM_PACKAGE_SOURCES) {
    print(indentedString(
        'File `$fileName` was not found in package sources list. Used here:',
        indents: 2));
  } else if (fileState == ImportResult_State.FILE_MISSING) {
    print(indentedString(
        'File `$fileName` does not exist on the filesystem. Used here:',
        indents: 2));
  } else {
    print(indentedString('File `$fileName` could not be found. Used here:',
        indents: 2));
  }
  for (var importer in flatResults) {
    print(indentedString(
        'Line ${importer.importResult.lineInfo}: ${importer.filePath}',
        indents: 4));
  }
}

/// Prints package level warnings to stdout.
void printPackageWarnings(MapEntry packageResult) {
  Map<String, List<FlatResult>> byFile = groupBy(packageResult.value,
      (packageResult) => packageResult.importResult.resolvedLocation);
  if (packageResult.value[0].importResult.isDartPackageImported) {
    print(
        'Package ${packageResult.key} imported directly and errors found with files imported');
  } else if (packageResult.value[0].knownPackage) {
    print(
        'Package ${packageResult.key} imported transitively and errors found with files imported from it:');
  } else {
    print(
        'Package ${packageResult.key} was not a GN dep but files were imported from it:');
  }
  byFile.forEach(printFileWarnings);
}

/// Finds and prints warnings to stdout.
void printWarnings(
    {TargetCheckResult targetCheckResult,
    String outFile,
    PackageConfig resolver}) {
  final knownPackages =
      resolver.packages.map((package) => package.name).toList();

  final flatResults = targetCheckResult.files.expand((file) => file.imports.map(
      (importResult) => FlatResult(file.filePath, importResult,
          knownPackage: knownPackages.contains(importResult.dartPackage))));

  final notFoundResults = flatResults
      .where((result) => result.importResult.state != ImportResult_State.FOUND);

  final notFoundByPackage =
      groupBy(notFoundResults, (result) => result.importResult.dartPackage);

  notFoundByPackage.entries.forEach(printPackageWarnings);
  if (notFoundByPackage.entries.isNotEmpty) {
    exitCode = -1;
  }
}

void main(List<String> args) async {
  var parser = ArgParser()
    ..addOption('metadata-file', help: 'collected metadata file from GN')
    ..addOption('output-file', help: 'output file to write result to')
    ..addOption('packages-file',
        help: 'packages file to read dependency info from');
  var parsedArgs = parser.parse(args);
  String inputFile = parsedArgs['metadata-file'];
  String outFile = parsedArgs['output-file'];
  String packagesFile = parsedArgs['packages-file'];
  PackageConfig resolver = await loadPackageConfig(File(packagesFile).absolute);
  String inputFileContents = File(inputFile).readAsStringSync();
  final targetCheckResult = dependency_check.checkBuildInfo(
      buildInfo: file_processor.buildInfoFromJson(inputFileContents),
      resolver: resolver);
  printWarnings(
      targetCheckResult: targetCheckResult,
      outFile: outFile,
      resolver: resolver);
  writeOutfile(outFile, targetCheckResult);
}
