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

import 'package:kernel/ast.dart';
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/library_index.dart' show LibraryIndex;

import 'utils.dart';

/// Tracks used getters and setters of generated protobuf message
/// classes and prunes metadata declarations.
class ProtobufHandler {
  static const String protobufLibraryUri = 'package:protobuf/protobuf.dart';
  static const String metadataFieldName = '_i';

  // All of those methods have the dart field name as second positional
  // parameter.
  // Method names are defined in:
  // https://github.com/dart-lang/protobuf/blob/master/protobuf/lib/src/protobuf/builder_info.dart
  // The code is generated by:
  // https://github.com/dart-lang/protobuf/blob/master/protoc_plugin/lib/protobuf_field.dart.
  static const Set<String> fieldAddingMethods = const <String>{
    'a',
    'aOM',
    'aOS',
    'aQM',
    'pPS',
    'aQS',
    'aInt64',
    'aOB',
    'e',
    'p',
    'pc',
    'm',
  };

  final CoreTypes coreTypes;
  final Class _generatedMessageClass;
  final Class _tagNumberClass;
  final Field _tagNumberField;
  final Class _builderInfoClass;
  final Procedure _builderInfoAddMethod;
  final _messageClasses = <Class, _MessageClass>{};
  final _invalidatedClasses = <_MessageClass>{};

  /// Creates [ProtobufHandler] instance for [component].
  /// Returns null if protobuf library is not used.
  static ProtobufHandler forComponent(
      Component component, CoreTypes coreTypes) {
    final libraryIndex = LibraryIndex(component, [protobufLibraryUri]);
    if (!libraryIndex.containsLibrary(protobufLibraryUri)) {
      return null;
    }
    return ProtobufHandler._internal(libraryIndex, coreTypes);
  }

  ProtobufHandler._internal(LibraryIndex libraryIndex, this.coreTypes)
      : _generatedMessageClass =
            libraryIndex.getClass(protobufLibraryUri, 'GeneratedMessage'),
        _tagNumberClass =
            libraryIndex.getClass(protobufLibraryUri, 'TagNumber'),
        _tagNumberField = libraryIndex.getMember(
            protobufLibraryUri, 'TagNumber', 'tagNumber'),
        _builderInfoClass =
            libraryIndex.getClass(protobufLibraryUri, 'BuilderInfo'),
        _builderInfoAddMethod =
            libraryIndex.getMember(protobufLibraryUri, 'BuilderInfo', 'add');

  /// This method is called from summary collector when analysis discovered
  /// that [member] is called and needs to construct a summary for its body.
  ///
  /// At this point protobuf handler can
  ///  - modify static field initializer of metadata field;
  ///  - track used members of the generated message classes.
  void beforeSummaryCreation(Member member) {
    // Only interested in members of subclasses of GeneratedMessage class.
    final cls = member.enclosingClass;
    if (cls == null || cls.superclass != _generatedMessageClass) {
      return;
    }
    final messageClass = (_messageClasses[cls] ??= _MessageClass());
    if (member is Field && member.name.text == metadataFieldName) {
      // Update contents of static field initializer of metadata field (_i).
      // according to the used tag numbers.
      assertx(member.isStatic);
      if (messageClass._metadataField == null) {
        messageClass._metadataField = member;
        ++Statistics.protobufMessagesUsed;
      } else {
        assertx(messageClass._metadataField == member);
      }
      _updateMetadataField(messageClass);
      return;
    }
    if (member is Procedure && !member.isStatic) {
      // Track usage of accessors of protobuf fields: extract tag number
      // from annotations and add tag number to the set of used tags.
      // This may also add message class to the set of invalidated classes,
      // so their metadata field initializers will be revisited.
      for (var annotation in member.annotations) {
        final constant = (annotation as ConstantExpression).constant;
        if (constant is InstanceConstant &&
            constant.classReference == _tagNumberClass.reference) {
          if (messageClass._usedTags.add(
              (constant.fieldValues[_tagNumberField.reference] as IntConstant)
                  .value)) {
            _invalidatedClasses.add(messageClass);
          }
        }
      }
    }
  }

  List<Field> getInvalidatedFields() {
    final fields = <Field>[];
    for (var cls in _invalidatedClasses) {
      if (cls._metadataField != null) {
        fields.add(cls._metadataField);
      }
    }
    _invalidatedClasses.clear();
    return fields;
  }

  /// Updates initializer of metadata field of [cls] message class.
  void _updateMetadataField(_MessageClass cls) {
    ++Statistics.protobufMetadataInitializersUpdated;
    Statistics.protobufMetadataFieldsPruned -= cls.numberOfFieldsPruned;

    final field = cls._metadataField;
    if (cls._originalInitializer == null) {
      cls._originalInitializer = field.initializer;
    }
    final cloner = CloneVisitorNotMembers();
    field.initializer = cloner.clone(cls._originalInitializer)..parent = field;
    final transformer = _MetadataTransformer(this, cls);
    field.initializer.accept(transformer);
    _invalidatedClasses.remove(cls);

    cls.numberOfFieldsPruned = transformer.numberOfFieldsPruned;
    Statistics.protobufMetadataFieldsPruned += cls.numberOfFieldsPruned;
  }

  bool _isUnusedMetadata(_MessageClass cls, MethodInvocation node) {
    if (node.interfaceTarget != null &&
        node.interfaceTarget.enclosingClass == _builderInfoClass &&
        fieldAddingMethods.contains(node.name.text)) {
      final tagNumber = (node.arguments.positional[0] as IntLiteral).value;
      return !cls._usedTags.contains(tagNumber);
    }
    return false;
  }
}

class _MessageClass {
  Field _metadataField;
  Expression _originalInitializer;
  final _usedTags = <int>{};
  int numberOfFieldsPruned = 0;
}

class _MetadataTransformer extends Transformer {
  final ProtobufHandler ph;
  final _MessageClass cls;
  int numberOfFieldsPruned = 0;

  _MetadataTransformer(this.ph, this.cls);

  @override
  TreeNode visitMethodInvocation(MethodInvocation node) {
    if (!ph._isUnusedMetadata(cls, node)) {
      super.visitMethodInvocation(node);
      return node;
    }
    // Replace the field metadata method with a dummy call to
    // `BuilderInfo.add`. This is to preserve the index calculations when
    // removing a field.
    // Change the tag-number to 0. Otherwise the decoder will get confused.
    ++numberOfFieldsPruned;
    return MethodInvocation(
        node.receiver,
        ph._builderInfoAddMethod.name,
        Arguments(
          <Expression>[
            IntLiteral(0), // tagNumber
            NullLiteral(), // name
            NullLiteral(), // fieldType
            NullLiteral(), // defaultOrMaker
            NullLiteral(), // subBuilder
            NullLiteral(), // valueOf
            NullLiteral(), // enumValues
          ],
          types: <DartType>[ph.coreTypes.nullType],
        ),
        ph._builderInfoAddMethod)
      ..fileOffset = node.fileOffset;
  }
}
