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

part of protoc;

/// Generates the Dart enum corresponding to a oneof declaration.
///
/// The enum is used to represent the state of a oneof when using the
/// corresponding which-method.
class OneofEnumGenerator {
  static void generate(
      IndentingWriter out, String classname, List<ProtobufField> fields) {
    out.addBlock('enum ${classname} {', '}\n', () {
      for (ProtobufField field in fields) {
        final name = oneofEnumMemberName(field.memberNames.fieldName);
        out.println('$name, ');
      }
      out.println('notSet');
    });
  }
}

class MessageGenerator extends ProtobufContainer {
  /// The name of the Dart class to generate.
  final String classname;

  /// The fully-qualified name of the message (without any leading '.').
  final String fullName;

  /// The part of the fully qualified name that comes after the package prefix.
  ///
  /// For nested messages this will include the names of the parents.
  ///
  /// For example:
  /// ```
  /// package foo;
  ///
  /// message Container {
  ///   message Nested {
  ///     int32 int32_value = 1;
  ///   }
  /// }
  /// ```
  /// The nested message will have a `fullName` of 'foo.Container.Nested', and a
  /// `messageName` of 'Container.Nested'.
  String get messageName =>
      fullName.substring(package.isEmpty ? 0 : package.length + 1);

  PbMixin mixin;

  final ProtobufContainer _parent;
  final DescriptorProto _descriptor;
  final List<EnumGenerator> _enumGenerators = <EnumGenerator>[];
  final List<MessageGenerator> _messageGenerators = <MessageGenerator>[];
  final List<ExtensionGenerator> _extensionGenerators = <ExtensionGenerator>[];
  // Stores the list of fields belonging to each oneof declaration identified
  // by the index in the containing types's oneof_decl list.
  final List<List<ProtobufField>> _oneofFields;
  List<OneofNames> _oneofNames;

  List<int> _fieldPath;
  final List<int> _fieldPathSegment;

  /// See [[ProtobufContainer]
  List<int> get fieldPath =>
      _fieldPath ??= List.from(_parent.fieldPath)..addAll(_fieldPathSegment);

  // populated by resolve()
  List<ProtobufField> _fieldList;

  Set<String> _usedTopLevelNames;

  MessageGenerator._(
      DescriptorProto descriptor,
      ProtobufContainer parent,
      Map<String, PbMixin> declaredMixins,
      PbMixin defaultMixin,
      this._usedTopLevelNames,
      int repeatedFieldIndex,
      int fieldIdTag)
      : _descriptor = descriptor,
        _parent = parent,
        _fieldPathSegment = [fieldIdTag, repeatedFieldIndex],
        classname = messageOrEnumClassName(descriptor.name, _usedTopLevelNames,
            parent: parent?.classname ?? ''),
        assert(parent != null),
        fullName = parent.fullName == ''
            ? descriptor.name
            : '${parent.fullName}.${descriptor.name}',
        _oneofFields =
            List.generate(descriptor.oneofDecl.length, (int index) => []) {
    mixin = _getMixin(declaredMixins, defaultMixin);
    for (var i = 0; i < _descriptor.enumType.length; i++) {
      EnumDescriptorProto e = _descriptor.enumType[i];
      _enumGenerators.add(EnumGenerator.nested(e, this, _usedTopLevelNames, i));
    }

    for (var i = 0; i < _descriptor.nestedType.length; i++) {
      DescriptorProto n = _descriptor.nestedType[i];
      _messageGenerators.add(MessageGenerator.nested(
          n, this, declaredMixins, defaultMixin, _usedTopLevelNames, i));
    }

    // Extensions within messages won't create top-level classes and don't need
    // to check against / be added to top-level reserved names.
    final usedExtensionNames = Set<String>()..addAll(forbiddenExtensionNames);
    for (var i = 0; i < _descriptor.extension.length; i++) {
      FieldDescriptorProto x = _descriptor.extension[i];
      _extensionGenerators
          .add(ExtensionGenerator.nested(x, this, usedExtensionNames, i));
    }
  }

  static const _topLevelMessageTag = 4;
  static const _nestedMessageTag = 3;
  static const _messageFieldTag = 2;

  MessageGenerator.topLevel(
      DescriptorProto descriptor,
      ProtobufContainer parent,
      Map<String, PbMixin> declaredMixins,
      PbMixin defaultMixin,
      Set<String> usedNames,
      int repeatedFieldIndex)
      : this._(descriptor, parent, declaredMixins, defaultMixin, usedNames,
            repeatedFieldIndex, _topLevelMessageTag);

  MessageGenerator.nested(
      DescriptorProto descriptor,
      ProtobufContainer parent,
      Map<String, PbMixin> declaredMixins,
      PbMixin defaultMixin,
      Set<String> usedNames,
      int repeatedFieldIndex)
      : this._(descriptor, parent, declaredMixins, defaultMixin, usedNames,
            repeatedFieldIndex, _nestedMessageTag);

  String get package => _parent.package;

  /// The generator of the .pb.dart file that will declare this type.
  FileGenerator get fileGen => _parent.fileGen;

  /// Throws an exception if [resolve] hasn't been called yet.
  void checkResolved() {
    if (_fieldList == null) {
      throw StateError("message not resolved: ${fullName}");
    }
  }

  /// Returns a const expression that evaluates to the JSON for this message.
  /// [usage] represents the .pb.dart file where the expression will be used.
  String getJsonConstant(FileGenerator usage) {
    var name = "$classname\$json";
    if (usage.protoFileUri == fileGen.protoFileUri) {
      return name;
    }
    return "$fileImportPrefix.$name";
  }

  /// Adds all mixins used in this message and any submessages.
  void addMixinsTo(Set<PbMixin> output) {
    if (mixin != null) {
      output.addAll(mixin.findMixinsToApply());
    }
    for (var m in _messageGenerators) {
      m.addMixinsTo(output);
    }
  }

  // Registers message and enum types that can be used elsewhere.
  void register(GenerationContext ctx) {
    ctx.registerFieldType(this);
    for (var m in _messageGenerators) {
      m.register(ctx);
    }
    for (var e in _enumGenerators) {
      e.register(ctx);
    }
  }

  // Creates fields and resolves extension targets.
  void resolve(GenerationContext ctx) {
    if (_fieldList != null) throw StateError("message already resolved");

    var reserved = mixin?.findReservedNames() ?? const <String>[];
    MemberNames members = messageMemberNames(
        _descriptor, classname, _usedTopLevelNames,
        reserved: reserved);

    _fieldList = <ProtobufField>[];
    for (FieldNames names in members.fieldNames) {
      ProtobufField field = ProtobufField.message(names, this, ctx);
      if (field.descriptor.hasOneofIndex()) {
        _oneofFields[field.descriptor.oneofIndex].add(field);
      }
      _fieldList.add(field);
    }
    _oneofNames = members.oneofNames;

    for (var m in _messageGenerators) {
      m.resolve(ctx);
    }
    for (var x in _extensionGenerators) {
      x.resolve(ctx);
    }
  }

  bool get needsFixnumImport {
    if (_fieldList == null) throw StateError("message not resolved");
    for (var field in _fieldList) {
      if (field.needsFixnumImport) return true;
    }
    for (var m in _messageGenerators) {
      if (m.needsFixnumImport) return true;
    }
    for (var x in _extensionGenerators) {
      if (x.needsFixnumImport) return true;
    }
    return false;
  }

  /// Adds dependencies of [generate] to [imports].
  ///
  /// For each .pb.dart file that the generated code needs to import,
  /// add its generator.
  void addImportsTo(
      Set<FileGenerator> imports, Set<FileGenerator> enumImports) {
    if (_fieldList == null) throw StateError("message not resolved");
    for (var field in _fieldList) {
      var typeGen = field.baseType.generator;
      if (typeGen is EnumGenerator) {
        enumImports.add(typeGen.fileGen);
      } else if (typeGen != null) {
        imports.add(typeGen.fileGen);
      }
    }
    for (var m in _messageGenerators) {
      m.addImportsTo(imports, enumImports);
    }
    for (var x in _extensionGenerators) {
      x.addImportsTo(imports, enumImports);
    }
  }

  // Returns the number of enums in this message and all nested messages.
  int get enumCount {
    var count = _enumGenerators.length;
    for (var m in _messageGenerators) {
      count += m.enumCount;
    }
    return count;
  }

  /// Adds dependencies of [generateConstants] to [imports].
  ///
  /// For each .pbjson.dart file that the generated code needs to import,
  /// add its generator.
  void addConstantImportsTo(Set<FileGenerator> imports) {
    if (_fieldList == null) throw StateError("message not resolved");
    for (var m in _messageGenerators) {
      m.addConstantImportsTo(imports);
    }
    for (var x in _extensionGenerators) {
      x.addConstantImportsTo(imports);
    }
  }

  void generate(IndentingWriter out) {
    checkResolved();

    for (MessageGenerator m in _messageGenerators) {
      // Don't output the generated map entry type. Instead, the `PbMap` type
      // from the protobuf library is used to hold the keys and values.
      if (m._descriptor.options.hasMapEntry()) continue;
      m.generate(out);
    }

    for (OneofNames oneof in _oneofNames) {
      OneofEnumGenerator.generate(
          out, oneof.oneofEnumName, _oneofFields[oneof.index]);
    }

    var mixinClause = '';
    if (mixin != null) {
      var mixinNames =
          mixin.findMixinsToApply().map((m) => '$_mixinImportPrefix.${m.name}');
      mixinClause = ' with ${mixinNames.join(", ")}';
    }

    String packageClause = package == ''
        ? ''
        : ', package: const $_protobufImportPrefix.PackageName(\'$package\')';
    String proto3JsonClause = (mixin?.hasProto3JsonHelpers ?? false)
        ? ', toProto3Json: $_mixinImportPrefix.${mixin.name}.toProto3JsonHelper, '
            'fromProto3Json: $_mixinImportPrefix.${mixin.name}.fromProto3JsonHelper'
        : '';
    out.addAnnotatedBlock(
        'class ${classname} extends $_protobufImportPrefix.GeneratedMessage${mixinClause} {',
        '}', [
      NamedLocation(
          name: classname, fieldPathSegment: fieldPath, start: 'class '.length)
    ], () {
      for (OneofNames oneof in _oneofNames) {
        out.addBlock(
            'static const $_coreImportPrefix.Map<$_coreImportPrefix.int, ${oneof.oneofEnumName}> ${oneof.byTagMapName} = {',
            '};', () {
          for (ProtobufField field in _oneofFields[oneof.index]) {
            final oneofMemberName =
                oneofEnumMemberName(field.memberNames.fieldName);
            out.println(
                '${field.number} : ${oneof.oneofEnumName}.${oneofMemberName},');
          }
          out.println('0 : ${oneof.oneofEnumName}.notSet');
        });
      }
      out.addBlock(
          'static final $_protobufImportPrefix.BuilderInfo _i = '
              '$_protobufImportPrefix.BuilderInfo(\'${messageName}\'$packageClause'
              ', createEmptyInstance: create'
              '$proto3JsonClause)',
          ';', () {
        for (int oneof = 0; oneof < _oneofFields.length; oneof++) {
          List<int> tags =
              _oneofFields[oneof].map((ProtobufField f) => f.number).toList();
          out.println("..oo($oneof, ${tags})");
        }

        for (ProtobufField field in _fieldList) {
          out.println(field.generateBuilderInfoCall(fileGen, package));
        }

        if (_descriptor.extensionRange.isNotEmpty) {
          out.println('..hasExtensions = true');
        }
        if (!_hasRequiredFields(this, Set())) {
          out.println('..hasRequiredFields = false');
        }
      });

      for (ExtensionGenerator x in _extensionGenerators) {
        x.generate(out);
      }

      out.println();

      out.printlnAnnotated('${classname}._() : super();', [
        NamedLocation(name: classname, fieldPathSegment: fieldPath, start: 0)
      ]);
      out.println('factory ${classname}() => create();');
      out.println(
          'factory ${classname}.fromBuffer($_coreImportPrefix.List<$_coreImportPrefix.int> i,'
          ' [$_protobufImportPrefix.ExtensionRegistry r = $_protobufImportPrefix.ExtensionRegistry.EMPTY])'
          ' => create()..mergeFromBuffer(i, r);');
      out.println('factory ${classname}.fromJson($_coreImportPrefix.String i,'
          ' [$_protobufImportPrefix.ExtensionRegistry r = $_protobufImportPrefix.ExtensionRegistry.EMPTY])'
          ' => create()..mergeFromJson(i, r);');
      out.println('${classname} clone() =>'
          ' ${classname}()..mergeFromMessage(this);');
      out.println('$classname copyWith(void Function($classname) updates) =>'
          ' super.copyWith((message) => updates(message as $classname));');

      out.println('$_protobufImportPrefix.BuilderInfo get info_ => _i;');

      // Factory functions which can be used as default value closures.
      out.println("@${_coreImportPrefix}.pragma('dart2js:noInline')");
      out.println('static ${classname} create() => ${classname}._();');
      out.println('${classname} createEmptyInstance() => create();');

      out.println(
          'static $_protobufImportPrefix.PbList<${classname}> createRepeated() =>'
          ' $_protobufImportPrefix.PbList<${classname}>();');
      out.println("@${_coreImportPrefix}.pragma('dart2js:noInline')");
      out.println('static ${classname} getDefault() =>'
          ' _defaultInstance ??='
          ' $_protobufImportPrefix.GeneratedMessage.\$_defaultFor<${classname}>'
          '(create);');
      out.println('static ${classname} _defaultInstance;');

      generateFieldsAccessorsMutators(out);
      mixin?.injectHelpers(out);
    });
    out.println();
  }

  // Returns true if the message type has any required fields.  If it doesn't,
  // we can optimize out calls to its isInitialized()/_findInvalidFields()
  // methods.
  //
  // already_seen is used to avoid checking the same type multiple times
  // (and also to protect against unbounded recursion).
  bool _hasRequiredFields(MessageGenerator type, Set alreadySeen) {
    if (type._fieldList == null) throw StateError("message not resolved");

    if (alreadySeen.contains(type.fullName)) {
      // The type is already in cache.  This means that either:
      // a. The type has no required fields.
      // b. We are in the midst of checking if the type has required fields,
      //    somewhere up the stack.  In this case, we know that if the type
      //    has any required fields, they'll be found when we return to it,
      //    and the whole call to HasRequiredFields() will return true.
      //    Therefore, we don't have to check if this type has required fields
      //    here.
      return false;
    }
    alreadySeen.add(type.fullName);
    // If the type has extensions, an extension with message type could contain
    // required fields, so we have to be conservative and assume such an
    // extension exists.
    if (type._descriptor.extensionRange.isNotEmpty) {
      return true;
    }

    for (ProtobufField field in type._fieldList) {
      if (field.isRequired) {
        return true;
      }
      if (field.baseType.isMessage) {
        MessageGenerator child = field.baseType.generator;
        if (_hasRequiredFields(child, alreadySeen)) {
          return true;
        }
      }
    }
    return false;
  }

  void generateFieldsAccessorsMutators(IndentingWriter out) {
    _oneofNames
        .forEach((OneofNames oneof) => generateOneofAccessors(out, oneof));

    for (var field in _fieldList) {
      out.println();
      List<int> memberFieldPath = List.from(fieldPath)
        ..addAll([_messageFieldTag, field.sourcePosition]);
      generateFieldAccessorsMutators(field, out, memberFieldPath);
    }
  }

  void generateOneofAccessors(IndentingWriter out, OneofNames oneof) {
    out.println();
    out.println("${oneof.oneofEnumName} ${oneof.whichOneofMethodName}() "
        "=> ${oneof.byTagMapName}[\$_whichOneof(${oneof.index})];");
    out.println('void ${oneof.clearMethodName}() '
        '=> clearField(\$_whichOneof(${oneof.index}));');
  }

  void generateFieldAccessorsMutators(
      ProtobufField field, IndentingWriter out, List<int> memberFieldPath) {
    var fieldTypeString = field.getDartType(fileGen);
    var defaultExpr = field.getDefaultExpr();
    var names = field.memberNames;

    _emitDeprecatedIf(field.isDeprecated, out);
    _emitOverrideIf(field.overridesGetter, out);
    _emitIndexAnnotation(field.number, out);
    final getterExpr = _getterExpression(fieldTypeString, field.index,
        defaultExpr, field.isRepeated, field.isMapField);
    out.printlnAnnotated(
        '${fieldTypeString} get ${names.fieldName} => ${getterExpr};', [
      NamedLocation(
          name: names.fieldName,
          fieldPathSegment: memberFieldPath,
          start: '${fieldTypeString} get '.length)
    ]);

    if (field.isRepeated) {
      if (field.overridesSetter) {
        throw 'Field ${field.fullName} cannot override a setter for '
            '${names.fieldName} because it is repeated.';
      }
      if (field.overridesHasMethod) {
        throw 'Field ${field.fullName} cannot override '
            '${names.hasMethodName}() because it is repeated.';
      }
      if (field.overridesClearMethod) {
        throw 'Field ${field.fullName} cannot override '
            '${names.clearMethodName}() because it is repeated.';
      }
    } else {
      var fastSetter = field.baseType.setter;
      _emitDeprecatedIf(field.isDeprecated, out);
      _emitOverrideIf(field.overridesSetter, out);
      _emitIndexAnnotation(field.number, out);
      if (fastSetter != null) {
        out.printlnAnnotated(
            'set ${names.fieldName}'
            '($fieldTypeString v) { '
            '$fastSetter(${field.index}, v);'
            ' }',
            [
              NamedLocation(
                  name: names.fieldName,
                  fieldPathSegment: memberFieldPath,
                  start: 'set '.length)
            ]);
      } else {
        out.printlnAnnotated(
            'set ${names.fieldName}'
            '($fieldTypeString v) { '
            'setField(${field.number}, v);'
            ' }',
            [
              NamedLocation(
                  name: names.fieldName,
                  fieldPathSegment: memberFieldPath,
                  start: 'set '.length)
            ]);
      }
      _emitDeprecatedIf(field.isDeprecated, out);
      _emitOverrideIf(field.overridesHasMethod, out);
      _emitIndexAnnotation(field.number, out);
      out.printlnAnnotated(
          '$_coreImportPrefix.bool ${names.hasMethodName}() =>'
          ' \$_has(${field.index});',
          [
            NamedLocation(
                name: names.hasMethodName,
                fieldPathSegment: memberFieldPath,
                start: '$_coreImportPrefix.bool '.length)
          ]);
      _emitDeprecatedIf(field.isDeprecated, out);
      _emitOverrideIf(field.overridesClearMethod, out);
      _emitIndexAnnotation(field.number, out);
      out.printlnAnnotated(
          'void ${names.clearMethodName}() =>'
          ' clearField(${field.number});',
          [
            NamedLocation(
                name: names.clearMethodName,
                fieldPathSegment: memberFieldPath,
                start: 'void '.length)
          ]);
      if (field.baseType.isMessage) {
        _emitDeprecatedIf(field.isDeprecated, out);
        _emitIndexAnnotation(field.number, out);
        out.printlnAnnotated(
            '${fieldTypeString} ${names.ensureMethodName}() => '
            '\$_ensure(${field.index});',
            <NamedLocation>[
              NamedLocation(
                  name: names.ensureMethodName,
                  fieldPathSegment: memberFieldPath,
                  start: '${fieldTypeString} '.length)
            ]);
      }
    }
  }

  String _getterExpression(String fieldType, int index, String defaultExpr,
      bool isRepeated, bool isMapField) {
    if (isMapField) {
      return '\$_getMap($index)';
    }
    if (fieldType == '$_coreImportPrefix.String') {
      if (defaultExpr == '""' || defaultExpr == "''") {
        return '\$_getSZ($index)';
      }
      return '\$_getS($index, $defaultExpr)';
    }
    if (fieldType == '$_coreImportPrefix.bool') {
      if (defaultExpr == 'false') {
        return '\$_getBF($index)';
      }
      return '\$_getB($index, $defaultExpr)';
    }
    if (fieldType == '$_coreImportPrefix.int') {
      if (defaultExpr == '0') {
        return '\$_getIZ($index)';
      }
      return '\$_getI($index, $defaultExpr)';
    }
    if (fieldType == 'Int64' && defaultExpr == 'null') {
      return '\$_getI64($index)';
    }
    if (defaultExpr == 'null') {
      return isRepeated ? '\$_getList($index)' : '\$_getN($index)';
    }
    return '\$_get($index, $defaultExpr)';
  }

  void _emitDeprecatedIf(bool condition, IndentingWriter out) {
    if (condition) {
      out.println(
          '@$_coreImportPrefix.Deprecated(\'This field is deprecated.\')');
    }
  }

  void _emitOverrideIf(bool condition, IndentingWriter out) {
    if (condition) {
      out.println('@$_coreImportPrefix.override');
    }
  }

  void _emitIndexAnnotation(int index, IndentingWriter out) {
    out.println('@$_protobufImportPrefix.TagNumber($index)');
  }

  void generateEnums(IndentingWriter out) {
    for (EnumGenerator e in _enumGenerators) {
      e.generate(out);
    }

    for (MessageGenerator m in _messageGenerators) {
      m.generateEnums(out);
    }
  }

  /// Writes a Dart constant containing the JSON for the ProtoDescriptor.
  /// Also writes a separate constant for each nested message,
  /// to avoid duplication.
  void generateConstants(IndentingWriter out) {
    const nestedTypeTag = 3;
    const enumTypeTag = 4;
    assert(_descriptor.info_.fieldInfo[nestedTypeTag].name == "nestedType");
    assert(_descriptor.info_.fieldInfo[enumTypeTag].name == "enumType");

    var name = getJsonConstant(fileGen);
    var json = _descriptor.writeToJsonMap();
    var nestedTypeNames =
        _messageGenerators.map((m) => m.getJsonConstant(fileGen)).toList();
    var nestedEnumNames =
        _enumGenerators.map((e) => e.getJsonConstant(fileGen)).toList();

    out.addBlock("const $name = const {", "};", () {
      for (var key in json.keys) {
        out.print("'$key': ");
        if (key == "$nestedTypeTag") {
          // refer to message constants by name instead of repeating each value
          out.println("const [${nestedTypeNames.join(", ")}],");
          continue;
        } else if (key == "$enumTypeTag") {
          // refer to enum constants by name
          out.println("const [${nestedEnumNames.join(", ")}],");
          continue;
        }
        writeJsonConst(out, json[key]);
        out.println(",");
      }
    });
    out.println();

    for (var m in _messageGenerators) {
      m.generateConstants(out);
    }

    for (var e in _enumGenerators) {
      e.generateConstants(out);
    }
  }

  /// Returns the mixin for this message, or null if none.
  ///
  /// First searches [wellKnownMixins], then [declaredMixins],
  /// then internal mixins declared by [findMixin].
  PbMixin _getMixin(Map<String, PbMixin> declaredMixins, PbMixin defaultMixin) {
    PbMixin wellKnownMixin = wellKnownMixinForFullName(fullName);
    if (wellKnownMixin != null) return wellKnownMixin;
    if (!_descriptor.hasOptions() ||
        !_descriptor.options.hasExtension(Dart_options.mixin)) {
      return defaultMixin;
    }

    String name = _descriptor.options.getExtension(Dart_options.mixin);
    if (name.isEmpty) return null; // don't use any mixins (override default)
    var mixin = declaredMixins[name] ?? findMixin(name);
    if (mixin == null) {
      throw '${_descriptor.name} in ${_parent.fileGen.descriptor.name}: mixin "$name" not found';
    }
    return mixin;
  }
}
