// 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();
final String _protobufImportPrefix = r'$pb';
final String _asyncImportPrefix = r'$async';
const String _coreImportPrefix = r'$core';
final String _grpcImportPrefix = r'$grpc';
final String _protobufImport =
    "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;";
final String _asyncImport = "import 'dart:async' as $_asyncImportPrefix;";
final String _coreImport = "import 'dart:core' as $_coreImportPrefix";
final String _grpcImport =
    "import 'package:grpc/service_api.dart' as $_grpcImportPrefix;";

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

        bool declaredMixin = dartMixins.containsKey(parentName);
        bool 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 = Set<String>()
    ..addAll(toplevelReservedCapitalizedNames);

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

  final Set<String> usedExtensionNames = Set<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, usedTopLevelNames, i));
    }
    for (ServiceDescriptorProto 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;
  }

  String get package => descriptor.package;
  String get classname => '';
  String get fullName => descriptor.package;
  FileGenerator get fileGen => this;
  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");

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

    IndentingWriter mainWriter = generateMainFile(config);
    IndentingWriter 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");
    IndentingWriter out = makeWriter();

    writeMainHeader(out, config);

    // Generate code.
    for (MessageGenerator 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.
      String className = extensionClassName(descriptor, usedTopLevelNames);
      out.addBlock('class $className {', '}\n', () {
        for (ExtensionGenerator x in extensionGenerators) {
          x.generate(out);
        }
        out.println(
            'static void registerAllExtensions($_protobufImportPrefix.ExtensionRegistry '
            'registry) {');
        for (ExtensionGenerator x in extensionGenerators) {
          out.println('  registry.add(${x.name});');
        }
        out.println('}');
      });
    }

    for (ClientApiGenerator 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('// ignore: UNUSED_SHOWN_NAME');
    out.println(
        '$_coreImport show int, bool, double, String, List, Map, override;\n');

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

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

    var mixinImports = findMixinsToImport();
    var importNames = mixinImports.keys.toList();
    importNames.sort();
    for (var imp in importNames) {
      var symbols = mixinImports[imp];
      out.println("import '${imp}' show ${symbols.join(', ')};");
    }
    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();

    _writeWellKnownImports(out);

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

  void _writeWellKnownImports(IndentingWriter out) {
    for (final message in messageGenerators) {
      final importStatements =
          wellKnownTypeForFullName(message.fullName)?.extraImports ??
              <String>[];
      for (String importStatement in importStatements) {
        out.println(importStatement);
      }
    }
  }

  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 map from import names to the Dart symbols to be imported.
  Map<String, List<String>> findMixinsToImport() {
    var mixins = Set<PbMixin>();
    for (MessageGenerator m in messageGenerators) {
      m.addMixinsTo(mixins);
    }

    var imports = <String, List<String>>{};
    for (var m in mixins) {
      var imp = m.importFrom;
      List<String> symbols = imports[imp];
      if (symbols == null) {
        symbols = [];
        imports[imp] = symbols;
      }
      symbols.add(m.name);
    }

    for (var imp in imports.keys) {
      imports[imp].sort();
    }

    return imports;
  }

  /// 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,UNUSED_SHOWN_NAME");
      out.println("$_coreImport show int, dynamic, String, List, Map;");
      out.println(_protobufImport);
      out.println();
    }

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

    for (MessageGenerator 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 (MessageGenerator 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 show String, Map, ArgumentError, dynamic;");
    }

    // Import .pb.dart files needed for requests and responses.
    var imports = Set<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();
    }

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

    for (ServiceGenerator 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(_grpcImport);
    out.println();
    out.println("$_coreImport show int, String, List;\n");

    // Import .pb.dart files needed for requests and responses.
    var imports = Set<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 (MessageGenerator m in messageGenerators) {
      m.generateConstants(out);
    }
    for (ServiceGenerator 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}
///
// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import
''');
  }

  /// 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) {
    Uri resolvedImport =
        config.resolveImport(target.protoFileUri, protoFileUri, extension);
    out.print("import '$resolvedImport'");
    if (protoFileUri != target.protoFileUri) {
      out.print(' as ${target.fileImportPrefix}');
    }
    out.println(';');
  }
}
