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

final _dartIdentifier = RegExp(r'^\w+$');
final _formatter = DartFormatter();
const String _protobufImportPrefix = r'$pb';
const String _asyncImportPrefix = r'$async';
const String _coreImportPrefix = r'$core';
const String _fixnumImportPrefix = r'$fixnum';
const String _grpcImportPrefix = r'$grpc';
const String _mixinImportPrefix = r'$mixin';
const String _protobufImport =
    "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;";
const String _asyncImport = "import 'dart:async' as $_asyncImportPrefix;";
const String _coreImport = "import 'dart:core' as $_coreImportPrefix;";
const String _grpcImport =
    "import 'package:grpc/service_api.dart' as $_grpcImportPrefix;";

/// Generates code that will evaluate to the empty string if
/// `const bool.fromEnvironment(envName)` is `true` and evaluate to [value]
/// otherwise.
String configurationDependent(String envName, String value) {
  return 'const $_coreImportPrefix.bool.fromEnvironment(${quoted(envName)})'
      ' ? \'\' '
      ': $value';
}

/// Generates the Dart output files for one .proto input file.
///
/// Outputs include .pb.dart, pbenum.dart, and .pbjson.dart.
class FileGenerator extends ProtobufContainer {
  /// Reads and the declared mixins in the file, keyed by name.
  ///
  /// Performs some basic validation on declared mixins, e.g. whether names
  /// are valid dart identifiers and whether there are cycles in the `parent`
  /// hierarchy.
  /// Does not check for existence of import files or classes.
  static Map<String, PbMixin> _getDeclaredMixins(FileDescriptorProto desc) {
    String mixinError(String error) =>
        'Option "mixins" in ${desc.name}: $error';

    if (!desc.hasOptions() ||
        !desc.options.hasExtension(Dart_options.imports)) {
      return <String, PbMixin>{};
    }
    var dartMixins = <String, DartMixin>{};
    Imports importedMixins = desc.options.getExtension(Dart_options.imports);
    for (var mixin in importedMixins.mixins) {
      if (dartMixins.containsKey(mixin.name)) {
        throw mixinError('Duplicate mixin name: "${mixin.name}"');
      }
      if (!mixin.name.startsWith(_dartIdentifier)) {
        throw mixinError(
            '"${mixin.name}" is not a valid dart class identifier');
      }
      if (mixin.hasParent() && !mixin.parent.startsWith(_dartIdentifier)) {
        throw mixinError('Mixin parent "${mixin.parent}" of "${mixin.name}" is '
            'not a valid dart class identifier');
      }
      dartMixins[mixin.name] = mixin;
    }

    // Detect cycles and unknown parents.
    for (var mixin in dartMixins.values) {
      if (!mixin.hasParent()) continue;
      var currentMixin = mixin;
      var parentChain = <String>[];
      while (currentMixin.hasParent()) {
        var parentName = currentMixin.parent;

        var declaredMixin = dartMixins.containsKey(parentName);
        var internalMixin = !declaredMixin && findMixin(parentName) != null;

        if (internalMixin) break; // No further validation of parent chain.

        if (!declaredMixin) {
          throw mixinError('Unknown mixin parent "${mixin.parent}" of '
              '"${currentMixin.name}"');
        }

        if (parentChain.contains(parentName)) {
          var cycle = parentChain.join('->') + '->$parentName';
          throw mixinError('Cycle in parent chain: $cycle');
        }
        parentChain.add(parentName);
        currentMixin = dartMixins[parentName];
      }
    }

    // Turn DartMixins into PbMixins.
    final pbMixins = <String, PbMixin>{};
    PbMixin resolveMixin(String name) {
      if (pbMixins.containsKey(name)) return pbMixins[name];
      if (dartMixins.containsKey(name)) {
        var dartMixin = dartMixins[name];
        var pbMixin = PbMixin(dartMixin.name,
            importFrom: dartMixin.importFrom,
            parent: resolveMixin(dartMixin.parent));
        pbMixins[name] = pbMixin;
        return pbMixin;
      }
      return findMixin(name);
    }

    for (var mixin in dartMixins.values) {
      resolveMixin(mixin.name);
    }
    return pbMixins;
  }

  final FileDescriptorProto descriptor;
  final GenerationOptions options;

  // The relative path used to import the .proto file, as a URI.
  final Uri protoFileUri;

  final enumGenerators = <EnumGenerator>[];
  final messageGenerators = <MessageGenerator>[];
  final extensionGenerators = <ExtensionGenerator>[];
  final clientApiGenerators = <ClientApiGenerator>[];
  final serviceGenerators = <ServiceGenerator>[];
  final grpcGenerators = <GrpcServiceGenerator>[];

  /// Used to avoid collisions after names have been mangled to match the Dart
  /// style.
  final Set<String> usedTopLevelNames = <String>{}
    ..addAll(forbiddenTopLevelNames);

  /// Used to avoid collisions in the service file after names have been mangled
  /// to match the dart style.
  final Set<String> usedTopLevelServiceNames = <String>{}
    ..addAll(forbiddenTopLevelNames);

  final Set<String> usedExtensionNames = <String>{}
    ..addAll(forbiddenExtensionNames);

  /// True if cross-references have been resolved.
  bool _linked = false;

  FileGenerator(this.descriptor, this.options)
      : protoFileUri = Uri.file(descriptor.name) {
    if (protoFileUri.isAbsolute) {
      // protoc should never generate an import with an absolute path.
      throw "FAILURE: Import with absolute path is not supported";
    }

    var declaredMixins = _getDeclaredMixins(descriptor);
    var defaultMixinName =
        descriptor.options?.getExtension(Dart_options.defaultMixin) ?? '';
    var defaultMixin =
        declaredMixins[defaultMixinName] ?? findMixin(defaultMixinName);
    if (defaultMixin == null && defaultMixinName.isNotEmpty) {
      throw ('Option default_mixin on file ${descriptor.name}: Unknown mixin '
          '$defaultMixinName');
    }

    // Load and register all enum and message types.
    for (var i = 0; i < descriptor.enumType.length; i++) {
      enumGenerators.add(EnumGenerator.topLevel(
          descriptor.enumType[i], this, usedTopLevelNames, i));
    }
    for (var i = 0; i < descriptor.messageType.length; i++) {
      messageGenerators.add(MessageGenerator.topLevel(descriptor.messageType[i],
          this, declaredMixins, defaultMixin, usedTopLevelNames, i));
    }
    for (var i = 0; i < descriptor.extension.length; i++) {
      extensionGenerators.add(ExtensionGenerator.topLevel(
          descriptor.extension[i], this, usedExtensionNames, i));
    }
    for (var service in descriptor.service) {
      if (options.useGrpc) {
        grpcGenerators.add(GrpcServiceGenerator(service, this));
      } else {
        var serviceGen =
            ServiceGenerator(service, this, usedTopLevelServiceNames);
        serviceGenerators.add(serviceGen);
        clientApiGenerators
            .add(ClientApiGenerator(serviceGen, usedTopLevelNames));
      }
    }
  }

  /// Creates the fields in each message.
  /// Resolves field types and extension targets using the supplied context.
  void resolve(GenerationContext ctx) {
    if (_linked) throw StateError("cross references already resolved");

    for (var m in messageGenerators) {
      m.resolve(ctx);
    }
    for (var x in extensionGenerators) {
      x.resolve(ctx);
    }

    _linked = true;
  }

  @override
  String get package => descriptor.package;
  @override
  String get classname => '';
  @override
  String get fullName => descriptor.package;
  @override
  FileGenerator get fileGen => this;
  @override
  List<int> get fieldPath => [];

  /// Generates all the Dart files for this .proto file.
  List<CodeGeneratorResponse_File> generateFiles(OutputConfiguration config) {
    if (!_linked) throw StateError("not linked");

    CodeGeneratorResponse_File makeFile(String extension, String content) {
      var protoUrl = Uri.file(descriptor.name);
      var dartUrl = config.outputPathFor(protoUrl, extension);
      return CodeGeneratorResponse_File()
        ..name = dartUrl.path
        ..content = content;
    }

    var mainWriter = generateMainFile(config);
    var enumWriter = generateEnumFile(config);

    final files = [
      makeFile(".pb.dart", mainWriter.toString()),
      makeFile(".pbenum.dart", enumWriter.toString()),
      makeFile(".pbjson.dart", generateJsonFile(config)),
    ];

    if (options.generateMetadata) {
      files.addAll([
        makeFile(".pb.dart.meta",
            mainWriter.sourceLocationInfo.writeToJson().toString()),
        makeFile(".pbenum.dart.meta",
            enumWriter.sourceLocationInfo.writeToJson().toString())
      ]);
    }
    if (options.useGrpc) {
      if (grpcGenerators.isNotEmpty) {
        files.add(makeFile(".pbgrpc.dart", generateGrpcFile(config)));
      }
    } else {
      files.add(makeFile(".pbserver.dart", generateServerFile(config)));
    }
    return files;
  }

  /// Creates an IndentingWriter with metadata generation enabled or disabled.
  IndentingWriter makeWriter() => IndentingWriter(
      filename: options.generateMetadata ? descriptor.name : null);

  /// Returns the contents of the .pb.dart file for this .proto file.
  IndentingWriter generateMainFile(
      [OutputConfiguration config = const DefaultOutputConfiguration()]) {
    if (!_linked) throw StateError("not linked");
    var out = makeWriter();

    writeMainHeader(out, config);

    // Generate code.
    for (var m in messageGenerators) {
      m.generate(out);
    }

    // Generate code for extensions defined at top-level using a class
    // name derived from the file name.
    if (extensionGenerators.isNotEmpty) {
      // TODO(antonm): do not generate a class.
      var className = extensionClassName(descriptor, usedTopLevelNames);
      out.addBlock('class $className {', '}\n', () {
        for (var x in extensionGenerators) {
          x.generate(out);
        }
        out.println(
            'static void registerAllExtensions($_protobufImportPrefix.ExtensionRegistry '
            'registry) {');
        for (var x in extensionGenerators) {
          out.println('  registry.add(${x.name});');
        }
        out.println('}');
      });
    }

    for (var c in clientApiGenerators) {
      c.generate(out);
    }
    return out;
  }

  /// Writes the header and imports for the .pb.dart file.
  void writeMainHeader(IndentingWriter out,
      [OutputConfiguration config = const DefaultOutputConfiguration()]) {
    _writeHeading(out);

    // We only add the dart:async import if there are generic client API
    // generators for services in the FileDescriptorProto.
    if (clientApiGenerators.isNotEmpty) {
      out.println(_asyncImport);
    }

    out.println(_coreImport);
    out.println();

    if (_needsFixnumImport) {
      out.println(
          "import 'package:fixnum/fixnum.dart' as $_fixnumImportPrefix;");
    }

    if (_needsProtobufImport) {
      out.println(_protobufImport);
      out.println();
    }

    final mixinImports = findMixinImports();
    for (var libraryUri in mixinImports) {
      out.println("import '$libraryUri' as $_mixinImportPrefix;");
    }
    if (mixinImports.isNotEmpty) out.println();

    // Import the .pb.dart files we depend on.
    var imports = Set<FileGenerator>.identity();
    var enumImports = Set<FileGenerator>.identity();
    _findProtosToImport(imports, enumImports);

    for (var target in imports) {
      _writeImport(out, config, target, ".pb.dart");
    }
    if (imports.isNotEmpty) out.println();

    for (var target in enumImports) {
      _writeImport(out, config, target, ".pbenum.dart");
    }
    if (enumImports.isNotEmpty) out.println();

    for (var publicDependency in descriptor.publicDependency) {
      _writeExport(out, config,
          Uri.file(descriptor.dependency[publicDependency]), '.pb.dart');
    }

    // Export enums in main file for backward compatibility.
    if (enumCount > 0) {
      var resolvedImport =
          config.resolveImport(protoFileUri, protoFileUri, ".pbenum.dart");
      out.println("export '$resolvedImport';");
      out.println();
    }
  }

  bool get _needsFixnumImport {
    for (var m in messageGenerators) {
      if (m.needsFixnumImport) return true;
    }
    for (var x in extensionGenerators) {
      if (x.needsFixnumImport) return true;
    }
    return false;
  }

  bool get _needsProtobufImport =>
      messageGenerators.isNotEmpty ||
      extensionGenerators.isNotEmpty ||
      clientApiGenerators.isNotEmpty;

  /// Returns the generator for each .pb.dart file we need to import.
  void _findProtosToImport(
      Set<FileGenerator> imports, Set<FileGenerator> enumImports) {
    for (var m in messageGenerators) {
      m.addImportsTo(imports, enumImports);
    }
    for (var x in extensionGenerators) {
      x.addImportsTo(imports, enumImports);
    }
    // Add imports needed for client-side services.
    for (var x in serviceGenerators) {
      x.addImportsTo(imports);
    }
    // Don't need to import self. (But we may need to import the enums.)
    imports.remove(this);
  }

  /// Returns a sorted list of imports needed to support all mixins.
  List<String> findMixinImports() {
    var mixins = <PbMixin>{};
    for (var m in messageGenerators) {
      m.addMixinsTo(mixins);
    }

    return mixins
        .map((mixin) => mixin.importFrom)
        .toSet()
        .toList(growable: false)
          ..sort();
  }

  /// Returns the contents of the .pbenum.dart file for this .proto file.
  IndentingWriter generateEnumFile(
      [OutputConfiguration config = const DefaultOutputConfiguration()]) {
    if (!_linked) throw StateError("not linked");

    var out = makeWriter();
    _writeHeading(out);

    if (enumCount > 0) {
      // Make sure any other symbols in dart:core don't cause name conflicts
      // with enums that have the same name.
      out.println("// ignore_for_file: UNDEFINED_SHOWN_NAME");
      out.println(_coreImport);
      out.println(_protobufImport);
      out.println();
    }

    for (var e in enumGenerators) {
      e.generate(out);
    }

    for (var m in messageGenerators) {
      m.generateEnums(out);
    }

    return out;
  }

  /// Returns the number of enum types generated in the .pbenum.dart file.
  int get enumCount {
    var count = enumGenerators.length;
    for (var m in messageGenerators) {
      count += m.enumCount;
    }
    return count;
  }

  /// Returns the contents of the .pbserver.dart file for this .proto file.
  String generateServerFile(
      [OutputConfiguration config = const DefaultOutputConfiguration()]) {
    if (!_linked) throw StateError("not linked");
    var out = makeWriter();
    _writeHeading(out);

    if (serviceGenerators.isNotEmpty) {
      out.println(_asyncImport);
      out.println();
      out.println(_protobufImport);
      out.println();
      out.println(_coreImport);
    }

    // Import .pb.dart files needed for requests and responses.
    var imports = <FileGenerator>{};
    for (var x in serviceGenerators) {
      x.addImportsTo(imports);
    }
    for (var target in imports) {
      _writeImport(out, config, target, ".pb.dart");
    }

    // Import .pbjson.dart file needed for $json and $messageJson.
    if (serviceGenerators.isNotEmpty) {
      _writeImport(out, config, this, ".pbjson.dart");
      out.println();
    }

    var resolvedImport =
        config.resolveImport(protoFileUri, protoFileUri, ".pb.dart");
    out.println("export '$resolvedImport';");
    out.println();

    for (var s in serviceGenerators) {
      s.generate(out);
    }

    return out.toString();
  }

  /// Returns the contents of the .pbgrpc.dart file for this .proto file.
  String generateGrpcFile(
      [OutputConfiguration config = const DefaultOutputConfiguration()]) {
    if (!_linked) throw StateError("not linked");
    var out = makeWriter();
    _writeHeading(out);

    out.println(_asyncImport);
    out.println();
    out.println(_coreImport);
    out.println();
    out.println(_grpcImport);

    // Import .pb.dart files needed for requests and responses.
    var imports = <FileGenerator>{};
    for (var generator in grpcGenerators) {
      generator.addImportsTo(imports);
    }
    for (var target in imports) {
      _writeImport(out, config, target, ".pb.dart");
    }

    var resolvedImport =
        config.resolveImport(protoFileUri, protoFileUri, ".pb.dart");
    out.println("export '$resolvedImport';");
    out.println();

    for (var generator in grpcGenerators) {
      generator.generate(out);
    }

    return _formatter.format(out.toString());
  }

  /// Returns the contents of the .pbjson.dart file for this .proto file.
  String generateJsonFile(
      [OutputConfiguration config = const DefaultOutputConfiguration()]) {
    if (!_linked) throw StateError("not linked");
    var out = makeWriter();
    _writeHeading(out);

    // Import the .pbjson.dart files we depend on.
    var imports = _findJsonProtosToImport();
    for (var target in imports) {
      _writeImport(out, config, target, ".pbjson.dart");
    }
    if (imports.isNotEmpty) out.println();

    for (var e in enumGenerators) {
      e.generateConstants(out);
    }
    for (var m in messageGenerators) {
      m.generateConstants(out);
    }
    for (var s in serviceGenerators) {
      s.generateConstants(out);
    }

    return out.toString();
  }

  /// Returns the generator for each .pbjson.dart file the generated
  /// .pbjson.dart needs to import.
  Set<FileGenerator> _findJsonProtosToImport() {
    var imports = Set<FileGenerator>.identity();
    for (var m in messageGenerators) {
      m.addConstantImportsTo(imports);
    }
    for (var x in extensionGenerators) {
      x.addConstantImportsTo(imports);
    }
    for (var x in serviceGenerators) {
      x.addConstantImportsTo(imports);
    }
    imports.remove(this); // Don't need to import self.
    return imports;
  }

  /// Writes the header at the top of the dart file.
  void _writeHeading(IndentingWriter out) {
    out.println('''
///
//  Generated code. Do not modify.
//  source: ${descriptor.name}
//
// @dart = 2.7
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
''');
  }

  /// Writes an import of a .dart file corresponding to a .proto file.
  /// (Possibly the same .proto file.)
  void _writeImport(IndentingWriter out, OutputConfiguration config,
      FileGenerator target, String extension) {
    var resolvedImport =
        config.resolveImport(target.protoFileUri, protoFileUri, extension);
    out.print("import '$resolvedImport'");

    // .pb.dart files should always be prefixed--the protoFileUri check
    // will evaluate to true not just for the main .pb.dart file based off
    // the proto file, but also for the .pbserver.dart, .pbgrpc.dart files.
    if ((extension == ".pb.dart") || protoFileUri != target.protoFileUri) {
      out.print(' as ${target.fileImportPrefix}');
    }
    out.println(';');
  }

  /// Writes an export of a pb.dart file corresponding to a .proto file.
  /// (Possibly the same .proto file.)
  void _writeExport(IndentingWriter out, OutputConfiguration config, Uri target,
      String extension) {
    var resolvedImport = config.resolveImport(target, protoFileUri, extension);
    out.println("export '$resolvedImport';");
  }
}
