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

library fasta.test.textual_outline_test;

import 'dart:io';
import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
    show ScannerConfiguration;
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:dart_style/dart_style.dart' show DartFormatter;
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/util/textual_outline.dart';
import 'package:testing/testing.dart'
    show
        Chain,
        ChainContext,
        Expectation,
        ExpectationSet,
        Result,
        Step,
        TestDescription;

import '../utils/kernel_chain.dart' show MatchContext;
import 'suite_utils.dart';
import '../testing/environment_keys.dart';
import '../testing/folder_options.dart';

const int minSupportedMajorVersion = 2;
const int minSupportedMinorVersion = 12;

const List<Map<String, String>> EXPECTATIONS = [
  {
    "name": "ExpectationFileMismatch",
    "group": "Fail",
  },
  {
    "name": "ExpectationFileMissing",
    "group": "Fail",
  },
  {
    "name": "EmptyOutput",
    "group": "Fail",
  },
  {
    "name": "UnknownChunk",
    "group": "Fail",
  },
  {
    "name": "FormatterCrash",
    "group": "Fail",
  },
];

Future<Context> createContext(Chain suite, Map<String, String> environment) {
  return new Future.value(new Context(suite.root, environment));
}

void main([List<String> arguments = const []]) => internalMain(
      createContext,
      arguments: arguments,
      displayName: "textual outline suite",
    );

class Context extends ChainContext with MatchContext {
  final SuiteFolderOptions suiteFolderOptions;
  final Map<ExperimentalFlag, bool> forcedExperimentalFlags;

  @override
  final bool updateExpectations;

  @override
  String get updateExpectationsOption =>
      '${EnvironmentKeys.updateExpectations}=true';

  @override
  bool get canBeFixWithUpdateExpectations => true;

  Context(Uri baseUri, Map<String, String> environment)
      : suiteFolderOptions = new SuiteFolderOptions(baseUri),
        updateExpectations =
            environment[EnvironmentKeys.updateExpectations] == "true",
        forcedExperimentalFlags =
            SuiteFolderOptions.computeForcedExperimentalFlags(environment);

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

  @override
  final ExpectationSet expectationSet =
      new ExpectationSet.fromJsonList(EXPECTATIONS);
}

class TextualOutline extends Step<TestDescription, TestDescription, Context> {
  const TextualOutline();

  @override
  String get name => "TextualOutline";

  @override
  Future<Result<TestDescription>> run(
      TestDescription description, Context context) async {
    FolderOptions folderOptions =
        context.suiteFolderOptions.computeFolderOptions(description);
    Map<ExperimentalFlag, bool> experimentalFlags = folderOptions
        .computeExplicitExperimentalFlags(context.forcedExperimentalFlags);
    Map<ExperimentalFlag, bool> experimentalFlagsExplicit =
        folderOptions.computeExplicitExperimentalFlags(const {});

    Uint8List bytes = new File.fromUri(description.uri).readAsBytesSync();
    for (bool modelled in [false, true]) {
      TextualOutlineInfoForTesting info = new TextualOutlineInfoForTesting();
      String? result = textualOutline(
        bytes,
        new ScannerConfiguration(
          enableExtensionMethods: isExperimentEnabled(
              ExperimentalFlag.extensionMethods,
              explicitExperimentalFlags: experimentalFlags),
          enableNonNullable: isExperimentEnabled(ExperimentalFlag.nonNullable,
              explicitExperimentalFlags: experimentalFlags),
          enableTripleShift: isExperimentEnabled(ExperimentalFlag.tripleShift,
              explicitExperimentalFlags: experimentalFlags),
        ),
        throwOnUnexpected: true,
        performModelling: modelled,
        returnNullOnError: false,
        enablePatterns: isExperimentEnabled(ExperimentalFlag.patterns,
            explicitExperimentalFlags: experimentalFlags),
        infoForTesting: info,
      );
      if (result == null) {
        return new Result(
            null, context.expectationSet["EmptyOutput"], description.uri);
      }

      bool containsUnknownChunk = info.hasUnknownChunk;
      bool tryFormat = !containsUnknownChunk;
      for (LanguageVersionToken version in info.languageVersionTokens) {
        if (version.major < minSupportedMajorVersion) {
          tryFormat = false;
        } else if (version.major == minSupportedMajorVersion &&
            version.minor < minSupportedMinorVersion) {
          tryFormat = false;
        }
      }
      dynamic formatterException;
      StackTrace? formatterExceptionSt;
      if (tryFormat) {
        try {
          List<String> experimentFlags = [];
          for (MapEntry<ExperimentalFlag, bool> entry
              in experimentalFlags.entries) {
            if (entry.value) {
              experimentFlags.add(entry.key.name);
            }
          }

          // Default to the latest language version. If the test should be at
          // an older language version, it will contain a `// @dart=x.y`
          // comment, which takes precedence over this argument.
          result = new DartFormatter(
                  languageVersion: DartFormatter.latestLanguageVersion,
                  experimentFlags: experimentFlags)
              .format(result);
        } catch (e, st) {
          formatterException = e;
          formatterExceptionSt = st;
        }
      }

      String filename = ".textual_outline.expect";
      if (modelled) {
        filename = ".textual_outline_modelled.expect";
      }

      Result<TestDescription> expectMatch =
          await context.match<TestDescription>(
              filename, result!, description.uri, description);
      if (expectMatch.outcome != Expectation.pass) return expectMatch;

      if (containsUnknownChunk) {
        return new Result(
            null, context.expectationSet["UnknownChunk"], description.uri);
      }

      if (formatterException != null && !info.hasParserErrors) {
        bool hasUnreleasedExperiment = false;
        for (MapEntry<ExperimentalFlag, bool> entry
            in experimentalFlagsExplicit.entries) {
          if (entry.value) {
            if (!entry.key.isEnabledByDefault) {
              hasUnreleasedExperiment = true;
              break;
            }
          }
        }
        if (!hasUnreleasedExperiment) {
          return new Result(null, context.expectationSet["FormatterCrash"],
              formatterException,
              trace: formatterExceptionSt);
        }
      }
    }

    return new Result.pass(description);
  }
}
