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

// @dart = 2.9

import 'dart:io' show Directory, Platform;
import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart'
    show ExperimentalFlag;
import 'package:front_end/src/base/nnbd_mode.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/src/printer.dart';

const String normalMarker = 'normal';
const String verboseMarker = 'verbose';
const String limitedMarker = 'limited';

const String statementMarker = 'stmt';
const String expressionMarker = 'expr';

const AstTextStrategy normalStrategy = const AstTextStrategy(
    includeLibraryNamesInMembers: false,
    includeLibraryNamesInTypes: false,
    includeAuxiliaryProperties: false,
    useMultiline: true,
    maxExpressionDepth: null,
    maxExpressionsLength: null,
    maxStatementDepth: null,
    maxStatementsLength: null);

const AstTextStrategy verboseStrategy = const AstTextStrategy(
    includeLibraryNamesInMembers: true,
    includeLibraryNamesInTypes: true,
    includeAuxiliaryProperties: true,
    useMultiline: true,
    maxExpressionDepth: null,
    maxExpressionsLength: null,
    maxStatementDepth: null,
    maxStatementsLength: null);

const AstTextStrategy limitedStrategy = const AstTextStrategy(
    includeLibraryNamesInMembers: false,
    includeLibraryNamesInTypes: false,
    includeAuxiliaryProperties: false,
    useMultiline: false,
    maxExpressionDepth: 5,
    maxExpressionsLength: 4,
    maxStatementDepth: 5,
    maxStatementsLength: 4);

AstTextStrategy getStrategy(String marker) {
  switch (marker) {
    case normalMarker:
      return normalStrategy;
    case verboseMarker:
      return verboseStrategy;
    case limitedMarker:
      return limitedStrategy;
  }
  throw new UnsupportedError("Unexpected marker '${marker}'.");
}

Future<void> main(List<String> args) async {
  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
  await runTests<String>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      preserveWhitespaceInAnnotations: true,
      runTest: runTestFor(const TextRepresentationDataComputer(), [
        const TextRepresentationConfig(normalMarker, 'normal'),
        const TextRepresentationConfig(verboseMarker, 'verbose'),
        const TextRepresentationConfig(limitedMarker, 'limited'),
      ]));
}

class TextRepresentationConfig extends TestConfig {
  const TextRepresentationConfig(String marker, String name)
      : super(marker, name,
            explicitExperimentalFlags: const {
              ExperimentalFlag.nonNullable: true
            },
            nnbdMode: NnbdMode.Strong);

  @override
  void customizeCompilerOptions(CompilerOptions options, TestData testData) {
    if (testData.name.endsWith('_opt_out.dart')) {
      options.nnbdMode = NnbdMode.Weak;
    }
  }
}

class TextRepresentationDataComputer extends DataComputer<String> {
  const TextRepresentationDataComputer();

  @override
  void computeLibraryData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Library library,
      Map<Id, ActualData<String>> actualMap,
      {bool verbose}) {
    new TextRepresentationDataExtractor(
            compilerResult, actualMap, getStrategy(config.marker))
        .computeForLibrary(library);
  }

  @override
  void computeMemberData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Member member,
      Map<Id, ActualData<String>> actualMap,
      {bool verbose}) {
    member.accept(new TextRepresentationDataExtractor(
        compilerResult, actualMap, getStrategy(config.marker)));
  }

  @override
  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
}

class TextRepresentationDataExtractor extends CfeDataExtractor<String> {
  final AstTextStrategy strategy;

  TextRepresentationDataExtractor(InternalCompilerResult compilerResult,
      Map<Id, ActualData<String>> actualMap, this.strategy)
      : super(compilerResult, actualMap);

  @override
  String computeLibraryValue(Id id, Library node) {
    return 'nnbd=${node.isNonNullableByDefault}';
  }

  @override
  void visitProcedure(Procedure node) {
    if (!node.name.text.startsWith(expressionMarker) &&
        !node.name.text.startsWith(statementMarker)) {
      node.function.accept(this);
    }
    computeForMember(node);
  }

  @override
  void visitField(Field node) {
    if (!node.name.text.startsWith(expressionMarker) &&
        !node.name.text.startsWith(statementMarker)) {
      node.initializer?.accept(this);
    }
    computeForMember(node);
  }

  @override
  String computeMemberValue(Id id, Member node) {
    if (node.name.text == 'stmtVariableDeclarationMulti') {
      print(node);
    }
    if (node.name.text.startsWith(expressionMarker)) {
      if (node is Procedure) {
        Statement body = node.function.body;
        if (body is ReturnStatement) {
          return body.expression.toText(strategy);
        }
      } else if (node is Field && node.initializer != null) {
        return node.initializer.toText(strategy);
      }
    } else if (node.name.text.startsWith(statementMarker)) {
      if (node is Procedure) {
        Statement body = node.function.body;
        if (body is Block && body.statements.length == 1) {
          // Prefix with newline to make multiline text representations more
          // readable.
          return '\n${body.statements.single.toText(strategy)}';
        }
      }
    }
    return null;
  }

  @override
  String computeNodeValue(Id id, TreeNode node) {
    if (node is ConstantExpression) {
      return node.constant.toText(strategy);
    } else if (node is VariableDeclaration) {
      DartType type = node.type;
      if (type is FunctionType && type.typedefType != null) {
        return type.typedefType.toText(strategy);
      } else {
        return type.toText(strategy);
      }
    }
    return null;
  }
}
