// Copyright (c) 2021, 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:convert' show jsonDecode;
import 'dart:io' show File;

import 'package:_fe_analyzer_shared/src/messages/severity.dart'
    show CfeSeverity;
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart';
import 'package:front_end/src/api_prototype/memory_file_system.dart';
import 'package:front_end/src/util/outline_extractor.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/src/equivalence.dart';
import 'package:testing/testing.dart'
    show Chain, ChainContext, ExpectationSet, Result, Step, TestDescription;

import 'utils/suite_utils.dart';
import 'testing/environment_keys.dart';
import 'incremental_suite.dart' as helper;
import 'testing_utils.dart' show checkEnvironment;
import 'utils/kernel_chain.dart' show MatchContext;

const String EXPECTATIONS = '''
[
  {
    "name": "ExpectationFileMismatch",
    "group": "Fail"
  },
  {
    "name": "ExpectationFileMissing",
    "group": "Fail"
  }
]
''';

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

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

  bool updateExpectations =
      environment[EnvironmentKeys.updateExpectations] == "true";

  return new Future.value(new Context(suite.name, updateExpectations));
}

class Context extends ChainContext with MatchContext {
  @override
  final bool updateExpectations;

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

  @override
  bool get canBeFixWithUpdateExpectations => true;

  final String suiteName;

  Context(this.suiteName, this.updateExpectations);

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

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

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

  @override
  String get name => "OutlineExtractorStep";

  @override
  Future<Result<TestDescription>> run(
    TestDescription description,
    Context context,
  ) async {
    Uri? packages = description.uri.resolve(".dart_tool/package_config.json");
    if (!new File.fromUri(packages).existsSync()) {
      packages = null;
    }
    Map<Uri, String> result = await extractOutline([
      description.uri,
    ], packages: packages);
    StringBuffer sb = new StringBuffer();
    Uri uri = description.uri;
    Uri base = uri.resolve(".");
    Uri dartBase = Uri.base;

    for (MapEntry<Uri, String> entry in result.entries) {
      sb.writeln("${entry.key}:");
      sb.writeln(entry.value);
      sb.writeln("\n\n");
    }

    String actual = sb.toString();
    actual = actual.replaceAll("$base", "org-dartlang-testcase:///");
    actual = actual.replaceAll("$dartBase", "org-dartlang-testcase-sdk:///");
    actual = actual.replaceAll("\\n", "\n");

    return context.match<TestDescription>(
      ".outline_extracted",
      actual,
      description.uri,
      description,
    );
  }
}

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

  @override
  String get name => "CompileAndCompare";

  @override
  Future<Result<TestDescription>> run(
    TestDescription description,
    Context context,
  ) async {
    Uri? packages = description.uri.resolve(".dart_tool/package_config.json");
    if (!new File.fromUri(packages).existsSync()) {
      packages = null;
    }
    Map<Uri, String> processedFiles = await extractOutline([
      description.uri,
    ], packages: packages);

    void onDiagnostic(CfeDiagnosticMessage message) {
      if (message.severity == CfeSeverity.error ||
          message.severity == CfeSeverity.warning) {
        throw ("Unexpected error: ${message.plainTextFormatted.join('\n')}");
      }
    }

    Library lib1;
    {
      CompilerOptions options = helper.getOptions();
      options.onDiagnostic = onDiagnostic;
      options.packagesFileUri = packages;
      helper.TestIncrementalCompiler compiler =
          new helper.TestIncrementalCompiler(
            options,
            description.uri,
            /* initializeFrom = */ null,
            /* outlineOnly = */ true,
          );
      IncrementalCompilerResult c = await compiler.computeDelta();
      lib1 = c.component.libraries.firstWhere(
        (element) => element.fileUri == description.uri,
      );
    }
    Library lib2;
    {
      CompilerOptions options = helper.getOptions();
      options.onDiagnostic = onDiagnostic;
      options.packagesFileUri = packages;
      MemoryFileSystem mfs = new MemoryFileSystem(Uri.base);
      if (packages != null) {
        mfs
            .entityForUri(packages)
            .writeAsBytesSync(
              await options.fileSystem.entityForUri(packages).readAsBytes(),
            );
      }
      if (options.sdkSummary != null) {
        mfs
            .entityForUri(options.sdkSummary!)
            .writeAsBytesSync(
              await options.fileSystem
                  .entityForUri(options.sdkSummary!)
                  .readAsBytes(),
            );
      }
      if (options.librariesSpecificationUri != null) {
        mfs
            .entityForUri(options.librariesSpecificationUri!)
            .writeAsBytesSync(
              await options.fileSystem
                  .entityForUri(options.librariesSpecificationUri!)
                  .readAsBytes(),
            );
      }
      for (MapEntry<Uri, String> entry in processedFiles.entries) {
        mfs.entityForUri(entry.key).writeAsStringSync(entry.value);
      }
      options.fileSystem = mfs;
      helper.TestIncrementalCompiler compiler =
          new helper.TestIncrementalCompiler(
            options,
            description.uri,
            /* initializeFrom = */ null,
            /* outlineOnly = */ true,
          );
      IncrementalCompilerResult c = await compiler.computeDelta();
      lib2 = c.component.libraries.firstWhere(
        (element) => element.fileUri == description.uri,
      );
    }
    EquivalenceResult result = checkEquivalence(
      lib1,
      lib2,
      strategy: const Strategy(),
    );

    if (result.isEquivalent) {
      return new Result<TestDescription>.pass(description);
    } else {
      print("Bad:");
      print(result);
      return new Result<TestDescription>.fail(
        description,
        /* error = */ result,
      );
    }
  }
}

class Strategy extends EquivalenceStrategy {
  const Strategy();

  @override
  bool checkTreeNode_fileOffset(
    EquivalenceVisitor visitor,
    TreeNode node,
    TreeNode other,
  ) {
    return true;
  }

  @override
  bool checkAssertStatement_conditionStartOffset(
    EquivalenceVisitor visitor,
    AssertStatement node,
    AssertStatement other,
  ) {
    return true;
  }

  @override
  bool checkAssertStatement_conditionEndOffset(
    EquivalenceVisitor visitor,
    AssertStatement node,
    AssertStatement other,
  ) {
    return true;
  }

  @override
  bool checkClass_startFileOffset(
    EquivalenceVisitor visitor,
    Class node,
    Class other,
  ) {
    return true;
  }

  @override
  bool checkClass_fileEndOffset(
    EquivalenceVisitor visitor,
    Class node,
    Class other,
  ) {
    return true;
  }

  @override
  bool checkProcedure_fileStartOffset(
    EquivalenceVisitor visitor,
    Procedure node,
    Procedure other,
  ) {
    return true;
  }

  @override
  bool checkConstructor_startFileOffset(
    EquivalenceVisitor visitor,
    Constructor node,
    Constructor other,
  ) {
    return true;
  }

  @override
  bool checkMember_fileEndOffset(
    EquivalenceVisitor visitor,
    Member node,
    Member other,
  ) {
    return true;
  }

  @override
  bool checkFunctionNode_fileEndOffset(
    EquivalenceVisitor visitor,
    FunctionNode node,
    FunctionNode other,
  ) {
    return true;
  }

  @override
  bool checkBlock_fileEndOffset(
    EquivalenceVisitor visitor,
    Block node,
    Block other,
  ) {
    return true;
  }

  @override
  bool checkLibrary_additionalExports(
    EquivalenceVisitor visitor,
    Library node,
    Library other,
  ) {
    return visitor.checkSets(
      node.additionalExports.toSet(),
      other.additionalExports.toSet(),
      visitor.matchReferences,
      visitor.checkReferences,
      'additionalExports',
    );
  }

  @override
  bool checkClass_procedures(
    EquivalenceVisitor visitor,
    Class node,
    Class other,
  ) {
    // Check procedures as a set instead of a list to allow for reordering.
    List<Procedure> a = node.procedures.toList();
    int sorter(Procedure x, Procedure y) {
      int result = x.name.text.compareTo(y.name.text);
      if (result != 0) return result;
      result = x.kind.index - y.kind.index;
      if (result != 0) return result;
      // other stuff?
      return 0;
    }

    a.sort(sorter);
    List<Procedure> b = other.procedures.toList();
    b.sort(sorter);
    // return visitor.checkSets(a.toSet(), b.toSet(),
    //     visitor.matchNamedNodes, visitor.checkNodes, 'procedures');

    return visitor.checkLists(a, b, visitor.checkNodes, 'procedures');
  }
}
