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

import 'gen/google/protobuf/compiler/plugin.pb.dart';

typedef OnError = void Function(String details);

/// Helper function implementing a generic option parser that reads
/// `request.parameters` and treats each token as either a flag ("name") or a
/// key-value pair ("name=value"). For each option "name", it looks up whether a
/// [SingleOptionParser] exists in [parsers] and delegates the actual parsing of
/// the option to it. Returns `true` if no errors were reported.
bool genericOptionsParser(
  CodeGeneratorRequest request,
  CodeGeneratorResponse response,
  Map<String, SingleOptionParser> parsers,
) {
  final parameter = request.parameter;
  final options = parameter.trim().split(',');
  final errors = [];

  for (var option in options) {
    option = option.trim();
    if (option.isEmpty) continue;
    void reportError(String details) {
      errors.add('Error found trying to parse the option: $option.\n$details');
    }

    final nameValue = option.split('=');
    if (nameValue.length != 1 && nameValue.length != 2) {
      reportError('Options should be a single token, or a name=value pair');
      continue;
    }
    final name = nameValue[0].trim();
    final parser = parsers[name];
    if (parser == null) {
      reportError('Unknown option ($name).');
      continue;
    }

    final value = nameValue.length > 1 ? nameValue[1].trim() : null;
    parser.parse(name, value, reportError);
  }

  if (errors.isEmpty) return true;

  response.error = errors.join('\n');
  return false;
}

/// Options expected by the protoc code generation compiler.
class GenerationOptions {
  final bool useGrpc;
  final bool generateMetadata;
  final bool disableConstructorArgs;

  GenerationOptions({
    this.useGrpc = false,
    this.generateMetadata = false,
    this.disableConstructorArgs = false,
  });
}

/// A parser for a name-value pair option. Options parsed in
/// [genericOptionsParser] delegate to instances of this class to
/// parse the value of a specific option.
abstract class SingleOptionParser {
  /// Parse the [name]=[value] value pair and report any errors to [onError]. If
  /// the option is a flag, [value] will be null. Note, [name] is commonly
  /// unused. It is provided because [SingleOptionParser] can be registered for
  /// multiple option names in [genericOptionsParser].
  void parse(String name, String? value, OnError onError);
}

class GrpcOptionParser implements SingleOptionParser {
  bool grpcEnabled = false;

  @override
  void parse(String name, String? value, OnError onError) {
    if (value != null) {
      onError('Invalid grpc option. No value expected.');
      return;
    }
    grpcEnabled = true;
  }
}

class GenerateMetadataParser implements SingleOptionParser {
  bool generateKytheInfo = false;

  @override
  void parse(String name, String? value, OnError onError) {
    if (value != null) {
      onError('Invalid generate_kythe_info option. No value expected.');
      return;
    }
    generateKytheInfo = true;
  }
}

class DisableConstructorArgsParser implements SingleOptionParser {
  bool value = false;

  @override
  void parse(String name, String? value, OnError onError) {
    if (value != null) {
      onError('Invalid disable_constructor_args option. No value expected.');
      return;
    }
    this.value = true;
  }
}

/// Parser used by the compiler, which supports the `rpc` option (see
/// [GrpcOptionParser]) and any additional option added in [parsers]. If
/// [parsers] has a key for `rpc`, it will be ignored.
GenerationOptions? parseGenerationOptions(
  CodeGeneratorRequest request,
  CodeGeneratorResponse response, [
  Map<String, SingleOptionParser>? parsers,
]) {
  final newParsers = <String, SingleOptionParser>{};
  if (parsers != null) newParsers.addAll(parsers);

  final grpcOptionParser = GrpcOptionParser();
  newParsers['grpc'] = grpcOptionParser;

  final generateMetadataParser = GenerateMetadataParser();
  newParsers['generate_kythe_info'] = generateMetadataParser;

  final disableConstructorArgsParser = DisableConstructorArgsParser();
  newParsers['disable_constructor_args'] = disableConstructorArgsParser;

  if (genericOptionsParser(request, response, newParsers)) {
    return GenerationOptions(
      useGrpc: grpcOptionParser.grpcEnabled,
      generateMetadata: generateMetadataParser.generateKytheInfo,
      disableConstructorArgs: disableConstructorArgsParser.value,
    );
  }
  return null;
}
