// 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.

import 'dart:io' show File;
import 'dart:typed_data' show Uint8List;

import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener;
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
    show FormalParameterKind, MemberKind, Parser;
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
    show ScannerConfiguration;
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
    show Utf8BytesScanner;
import 'package:front_end/src/base/command_line_reporting.dart'
    as command_line_reporting;
import 'package:front_end/src/source/diet_parser.dart'
    show useImplicitCreationExpressionInCfe;
import 'package:kernel/kernel.dart';
import 'package:package_config/package_config.dart';
import 'package:testing/testing.dart'
    show Chain, ChainContext, Result, Step, TestDescription;

import 'utils/suite_utils.dart';
import 'testing_utils.dart' show checkEnvironment, filterList;

void main([List<String> arguments = const []]) => internalMain(
  createContext,
  arguments: arguments,
  displayName: "lint suite",
  configurationPath: "../testing.json",
);

Future<Context> createContext(Chain suite, Map<String, String> environment) {
  const Set<String> knownEnvironmentKeys = {"onlyInGit"};
  checkEnvironment(environment, knownEnvironmentKeys);

  bool onlyInGit = environment["onlyInGit"] != "false";
  return new Future.value(new Context(onlyInGit: onlyInGit));
}

class LintTestDescription extends TestDescription {
  @override
  final String shortName;
  @override
  final Uri uri;
  final LintTestCache cache;
  final LintListener listener;

  LintTestDescription(this.shortName, this.uri, this.cache, this.listener) {
    this.listener.description = this;
    this.listener.uri = uri;
  }

  String getErrorMessage(int offset, int squigglyLength, String message) {
    cache.source ??= new Source(cache.lineStarts, cache.rawBytes!, uri, uri);
    Location location = cache.source!.getLocation(uri, offset);
    return command_line_reporting.formatErrorMessage(
      cache.source!.getTextLine(location.line),
      location,
      squigglyLength,
      uri.toString(),
      message,
    );
  }
}

class LintTestCache {
  Uint8List? rawBytes;
  late List<int> lineStarts;
  Source? source;
  Token? firstToken;
  PackageConfig? packages;
}

class Context extends ChainContext {
  final bool onlyInGit;
  Context({required this.onlyInGit});

  @override
  final List<Step> steps = const <Step>[const LintStep()];

  @override
  Future<List<LintTestDescription>> list(Chain suite) async {
    String rootString = "${suite.root}";
    Uri apiUnstableUri = Uri.base.resolve(
      "pkg/front_end/lib/src/api_unstable/",
    );
    String apiUnstableString = apiUnstableUri.toString();

    List<LintTestDescription> result = [];
    for (TestDescription description in await filterList(
      suite,
      onlyInGit,
      await super.list(suite),
    )) {
      String baseName = "${description.uri}".substring(rootString.length);
      baseName = baseName.substring(0, baseName.length - ".dart".length);
      LintTestCache cache = new LintTestCache();

      result.add(
        new LintTestDescription(
          "$baseName/ExplicitType",
          description.uri,
          cache,
          new ExplicitTypeLintListener(),
        ),
      );

      result.add(
        new LintTestDescription(
          "$baseName/ImportsTwice",
          description.uri,
          cache,
          new ImportsTwiceLintListener(),
        ),
      );

      if (!description.uri.toString().startsWith(apiUnstableString)) {
        result.add(
          new LintTestDescription(
            "$baseName/Exports",
            description.uri,
            cache,
            new ExportsLintListener(),
          ),
        );
      }
    }
    return result;
  }
}

class LintStep extends Step<LintTestDescription, LintTestDescription, Context> {
  const LintStep();

  @override
  String get name => "lint";

  @override
  Future<Result<LintTestDescription>> run(
    LintTestDescription description,
    Context context,
  ) async {
    if (description.cache.rawBytes == null) {
      File f = new File.fromUri(description.uri);
      Uint8List bytes = description.cache.rawBytes = f.readAsBytesSync();
      Utf8BytesScanner scanner = new Utf8BytesScanner(
        bytes,
        configuration: const ScannerConfiguration(enableTripleShift: true),
        includeComments: true,
        languageVersionChanged: (scanner, languageVersion) {
          // Nothing - but don't overwrite the previous settings.
        },
      );
      description.cache.firstToken = scanner.tokenize();
      description.cache.lineStarts = scanner.lineStarts;

      Uri packageConfig = description.uri.resolve(
        ".dart_tool/package_config.json",
      );
      while (true) {
        if (new File.fromUri(packageConfig).existsSync()) {
          break;
        }
        // Stupid bailout.
        if (packageConfig.pathSegments.length < Uri.base.pathSegments.length) {
          break;
        }
        packageConfig = packageConfig.resolve(
          "../../.dart_tool/package_config.json",
        );
      }

      File packageConfigUri = new File.fromUri(packageConfig);
      if (packageConfigUri.existsSync()) {
        description.cache.packages = await loadPackageConfigUri(packageConfig);
      }
    }

    if (description.cache.firstToken == null) {
      return crash(description, StackTrace.current);
    }

    Parser parser = new Parser(
      description.listener,
      useImplicitCreationExpression: useImplicitCreationExpressionInCfe,
      allowPatterns: true,
      enableFeatureEnhancedParts: true,
    );
    parser.parseUnit(description.cache.firstToken!);

    if (description.listener.problems.isEmpty) {
      return pass(description);
    }
    return fail(description, description.listener.problems.join("\n\n"));
  }
}

class LintListener extends Listener {
  List<String> problems = <String>[];
  late final LintTestDescription description;
  @override
  late final Uri uri;

  void onProblem(int offset, int squigglyLength, String message) {
    problems.add(description.getErrorMessage(offset, squigglyLength, message));
  }
}

class ExplicitTypeLintListener extends LintListener {
  List<LatestType> _latestTypes = <LatestType>[];

  @override
  void beginVariablesDeclaration(
    Token token,
    Token? lateToken,
    Token? varFinalOrConst,
  ) {
    if (!_latestTypes.last.type) {
      onProblem(
        varFinalOrConst!.offset,
        varFinalOrConst.length,
        "No explicit type.",
      );
    }
  }

  @override
  void handleType(Token beginToken, Token? questionMark) {
    _latestTypes.add(new LatestType(beginToken, true));
  }

  @override
  void handleNoType(Token lastConsumed) {
    _latestTypes.add(new LatestType(lastConsumed, false));
  }

  @override
  void endFunctionType(Token functionToken, Token? questionMark) {
    _latestTypes.add(new LatestType(functionToken, true));
  }

  @override
  void endTopLevelFields(
    Token? augmentToken,
    Token? externalToken,
    Token? staticToken,
    Token? covariantToken,
    Token? lateToken,
    Token? varFinalOrConst,
    int count,
    Token beginToken,
    Token endToken,
  ) {
    if (!_latestTypes.last.type) {
      onProblem(beginToken.offset, beginToken.length, "No explicit type.");
    }
    _latestTypes.removeLast();
  }

  @override
  void endClassFields(
    Token? abstractToken,
    Token? augmentToken,
    Token? externalToken,
    Token? staticToken,
    Token? covariantToken,
    Token? lateToken,
    Token? varFinalOrConst,
    int count,
    Token beginToken,
    Token endToken,
  ) {
    if (!_latestTypes.last.type) {
      onProblem(
        varFinalOrConst!.offset,
        varFinalOrConst.length,
        "No explicit type.",
      );
    }
    _latestTypes.removeLast();
  }

  @override
  void endFormalParameter(
    Token? thisKeyword,
    Token? superKeyword,
    Token? periodAfterThisOrSuper,
    Token nameToken,
    Token? initializerStart,
    Token? initializerEnd,
    FormalParameterKind kind,
    MemberKind memberKind,
  ) {
    _latestTypes.removeLast();
  }
}

class LatestType {
  final Token token;
  bool type;

  LatestType(this.token, this.type);
}

class ImportsTwiceLintListener extends LintListener {
  Map<Uri, Set<String?>> seenImports = {};

  Token? seenAsKeyword;

  @override
  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
    seenAsKeyword = asKeyword;
  }

  @override
  void endImport(Token importKeyword, Token? augmentToken, Token? semicolon) {
    Token importUriToken = importKeyword.next!;
    String importUri = importUriToken.lexeme;
    if (importUri.startsWith("r")) {
      importUri = importUri.substring(2, importUri.length - 1);
    } else {
      importUri = importUri.substring(1, importUri.length - 1);
    }
    Uri resolved = uri.resolve(importUri);
    if (resolved.isScheme("package")) {
      if (description.cache.packages != null) {
        resolved = description.cache.packages!.resolve(resolved)!;
      }
    }
    String? asName = seenAsKeyword?.lexeme;
    Set<String?> asNames = seenImports[resolved] ??= {};
    if (!asNames.add(asName)) {
      if (asName != null) {
        onProblem(
          importUriToken.offset,
          importUriToken.lexeme.length,
          "Uri '$resolved' already imported once as '${asName}'.",
        );
      } else {
        onProblem(
          importUriToken.offset,
          importUriToken.lexeme.length,
          "Uri '$resolved' already imported once.",
        );
      }
    }
  }
}

class ExportsLintListener extends LintListener {
  @override
  void endExport(Token exportKeyword, Token semicolon) {
    Token exportUriToken = exportKeyword.next!;
    String exportUri = exportUriToken.lexeme;
    if (exportUri.startsWith("r")) {
      exportUri = exportUri.substring(2, exportUri.length - 1);
    } else {
      exportUri = exportUri.substring(1, exportUri.length - 1);
    }
    Uri resolved = uri.resolve(exportUri);

    if (resolved.isScheme("package") && resolved.path.startsWith('kernel/')) {
      // Exporting from `package:kernel` is allowed.
      return;
    }

    // Allowlist specific exports.
    if (resolved.isScheme('package') &&
        ['_fe_analyzer_shared/src/macros/uri.dart'].contains(resolved.path)) {
      return;
    }

    if (resolved.isScheme("package")) {
      if (description.cache.packages != null) {
        resolved = description.cache.packages!.resolve(resolved)!;
      }
    }
    onProblem(
      exportUriToken.offset,
      exportUriToken.lexeme.length,
      "Exports disallowed internally.",
    );
  }
}
