// Copyright (c) 2014, 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.

/// Code generation for the file "matchers.dart".
import 'package:analyzer_utilities/tools.dart';

import 'api.dart';
import 'from_html.dart';
import 'implied_types.dart';
import 'to_html.dart';

final GeneratedFile target = GeneratedFile(
    'test/integration/support/protocol_matchers.dart', (String pkgPath) async {
  var visitor = CodegenMatchersVisitor(readApi(pkgPath));
  return visitor.collectCode(visitor.visitApi);
});

class CodegenMatchersVisitor extends HierarchicalApiVisitor with CodeGenerator {
  /// Visitor used to produce doc comments.
  final ToHtmlVisitor toHtmlVisitor;

  /// Short human-readable string describing the context of the matcher being
  /// created.
  String? context;

  CodegenMatchersVisitor(Api api)
      : toHtmlVisitor = ToHtmlVisitor(api),
        super(api) {
    codeGeneratorSettings.commentLineLength = 79;
    codeGeneratorSettings.docCommentStartMarker = null;
    codeGeneratorSettings.docCommentLineLeader = '/// ';
    codeGeneratorSettings.docCommentEndMarker = null;
    codeGeneratorSettings.languageName = 'dart';
  }

  /// Create a matcher for the part of the API called [name], optionally
  /// clarified by [nameSuffix]. The matcher should verify that its input
  /// matches the given [type].
  void makeMatcher(ImpliedType impliedType) {
    context = impliedType.humanReadableName;
    docComment(toHtmlVisitor.collectHtml(() {
      toHtmlVisitor.p(() {
        toHtmlVisitor.write(context!);
      });
      var type = impliedType.type;
      if (type != null) {
        toHtmlVisitor.showType(null, type);
      }
    }));
    write('final Matcher ${camelJoin(['is', impliedType.camelName])} = ');
    var type = impliedType.type;
    if (type == null) {
      write('isNull');
    } else {
      visitTypeDecl(type);
    }
    writeln(';');
    writeln();
  }

  /// Generate a map describing the given set of fields, for use as the
  /// 'requiredFields' or 'optionalFields' argument to the [MatchesJsonObject]
  /// constructor.
  void outputObjectFields(Iterable<TypeObjectField> fields) {
    if (fields.isEmpty) {
      write('null');
      return;
    }
    writeln('{');
    indent(() {
      var commaNeeded = false;
      for (var field in fields) {
        if (commaNeeded) {
          writeln(',');
        }
        write("'${field.name}': ");
        if (field.value != null) {
          write("equals('${field.value}')");
        } else {
          visitTypeDecl(field.type);
        }
        commaNeeded = true;
      }
      writeln();
    });
    write('}');
  }

  @override
  void visitApi() {
    outputHeader(year: '2017');
    writeln();
    writeln('/// Matchers for data types defined in the analysis server API.');
    writeln("import 'package:test/test.dart';");
    writeln();
    writeln("import 'integration_tests.dart';");
    writeln();
    var impliedTypes = computeImpliedTypes(api).values.toList();
    impliedTypes.sort((ImpliedType first, ImpliedType second) =>
        first.camelName.compareTo(second.camelName));
    for (var impliedType in impliedTypes) {
      makeMatcher(impliedType);
    }
  }

  @override
  void visitTypeEnum(TypeEnum typeEnum) {
    writeln("MatchesEnum('$context', [");
    indent(() {
      var commaNeeded = false;
      for (var value in typeEnum.values) {
        if (commaNeeded) {
          writeln(',');
        }
        write("'${value.value}'");
        commaNeeded = true;
      }
      writeln();
    });
    write('])');
  }

  @override
  void visitTypeList(TypeList typeList) {
    write('isListOf(');
    visitTypeDecl(typeList.itemType);
    write(')');
  }

  @override
  void visitTypeMap(TypeMap typeMap) {
    write('isMapOf(');
    visitTypeDecl(typeMap.keyType);
    write(', ');
    visitTypeDecl(typeMap.valueType);
    write(')');
  }

  @override
  void visitTypeObject(TypeObject typeObject) {
    writeln('LazyMatcher(() => MatchesJsonObject(');
    indent(() {
      write("'$context', ");
      var requiredFields =
          typeObject.fields.where((TypeObjectField field) => !field.optional);
      outputObjectFields(requiredFields);
      var optionalFields = typeObject.fields
          .where((TypeObjectField field) => field.optional)
          .toList();
      if (optionalFields.isNotEmpty) {
        write(', optionalFields: ');
        outputObjectFields(optionalFields);
      }
    });
    write('))');
  }

  @override
  void visitTypeReference(TypeReference typeReference) {
    var typeName = typeReference.typeName;
    if (typeName == 'long') {
      typeName = 'int';
    }
    write(camelJoin(['is', typeName]));
  }

  @override
  void visitTypeUnion(TypeUnion typeUnion) {
    var commaNeeded = false;
    write('isOneOf([');
    for (var choice in typeUnion.choices) {
      if (commaNeeded) {
        write(', ');
      }
      visitTypeDecl(choice);
      commaNeeded = true;
    }
    write('])');
  }
}
