// Copyright (c) 2023, 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 'dart:math';

import 'package:collection/collection.dart';

import 'json_schema.dart';
import 'json_schema_extensions.dart';

/// Generates Dart classes from the Debug Adapter Protocol's JSON Schema.
class CodeGenerator {
  /// Writes all required Dart classes for the supplied DAP [schema].
  void writeAll(IndentableStringBuffer buffer, JsonSchema schema) {
    _writeDefinitionClasses(buffer, schema);
    buffer.writeln();
    _writeBodyClasses(buffer, schema);
    buffer.writeln();
    _writeEventTypeLookup(buffer, schema);
    buffer.writeln();
    _writeCommandArgumentTypeLookup(buffer, schema);
  }

  /// Maps a name used in the DAP spec to a valid name for use in Dart.
  ///
  /// Reserved words like `default` will be mapped to a suitable alternative.
  /// Prefixed underscores are removed to avoid making things private.
  ///
  /// Underscores between words are swapped for camelCase.
  String _dartSafeName(String name) {
    const improvedName = {
      'default': 'defaultValue',
    };
    return improvedName[name] ??
        // Some types are prefixed with _ in the spec but that will make them
        // private in Dart and inaccessible to the adapter so we strip it off.
        name
            .replaceAll(RegExp(r'^_+'), '')
            // Also replace any other underscores to make camelCase
            .replaceAllMapped(
                RegExp(r'_(.)'), (m) => m.group(1)!.toUpperCase());
  }

  /// Re-wraps [lines] at [maxLength] to help keep comments for indented code
  /// within 80 characters.
  Iterable<String> _wrapLines(List<String> lines, int maxLength) sync* {
    lines = lines.map((l) => l.trimRight()).toList();
    for (var line in lines) {
      while (true) {
        if (line.length <= maxLength || line.startsWith('-')) {
          yield line;
          break;
        } else {
          var lastSpace = line.lastIndexOf(' ', max(maxLength, 0));
          // If there was no valid place to wrap, yield the whole string.
          if (lastSpace == -1) {
            yield line;
            break;
          } else {
            yield line.substring(0, lastSpace);
            line = line.substring(lastSpace + 1);
          }
        }
      }
    }
  }

  /// For each Response/Event class in the spec, generate a specific class to
  /// represent its body.
  ///
  /// These classes are used to simplify sending responses/events from the
  /// Debug Adapters by avoiding the need to construct the entire response/event
  /// which requires additional fields (for example the corresponding requests
  /// id/command and sequences):
  ///
  ///     this.sendResponse(FooBody(x: 1))
  ///
  /// instead of
  ///
  ///     this.sendResponse(Response(
  ///       seq: seq++,
  ///       request_seq: request.seq,
  ///       command: request.command,
  ///       body: {
  ///         x: 1
  ///         ...
  ///       }
  ///     ))
  void _writeBodyClasses(IndentableStringBuffer buffer, JsonSchema schema) {
    for (final entry in schema.definitions.entries.sortedBy((e) => e.key)) {
      final name = entry.key;
      final type = entry.value;
      final baseType = type.baseType;

      if (baseType?.refName == 'Response' || baseType?.refName == 'Event') {
        final baseClass = baseType?.refName == 'Event'
            ? JsonType.named(schema, 'EventBody')
            : null;
        final classProperties = schema.propertiesFor(type);
        final bodyProperty = classProperties['body'];
        var bodyPropertyProperties = bodyProperty?.properties;

        _writeClass(
          buffer,
          bodyProperty ?? JsonType.empty(schema),
          '${name}Body',
          bodyPropertyProperties ?? {},
          {},
          baseClass,
          null,
        );
      }
    }
  }

  /// Writes a `canParse` function for a DAP spec class.
  ///
  /// The function checks whether an Object? is a valid map that contains all
  /// required fields and matches the types of the spec class.
  ///
  /// This is used where the spec contains union classes and we need to decide
  /// which of the allowed types a given value is.
  void _writeCanParseMethod(
    IndentableStringBuffer buffer,
    JsonType type,
    Map<String, JsonType> properties, {
    required String? baseTypeRefName,
  }) {
    buffer
      ..writeIndentedln('static bool canParse(Object? obj) {')
      ..indent()
      ..writeIndentedln('if (obj is! Map<String, dynamic>) {')
      ..indent()
      ..writeIndentedln('return false;')
      ..outdent()
      ..writeIndentedln('}');
    // In order to consider this valid for parsing, all fields that must not be
    // undefined must be present and also type check for the correct type.
    // Any fields that are optional but present, must still type check.
    for (final entry in properties.entries.sortedBy((e) => e.key)) {
      final propertyName = entry.key;
      final propertyType = entry.value;
      final isOptional = !type.requiresField(propertyName);

      if (propertyType.isAny && isOptional) {
        continue;
      }

      buffer.writeIndented('if (');
      _writeTypeCheckCondition(buffer, propertyType, "obj['$propertyName']",
          isOptional: isOptional, invert: true);
      buffer
        ..writeln(') {')
        ..indent()
        ..writeIndentedln('return false;')
        ..outdent()
        ..writeIndentedln('}');
    }
    buffer
      ..writeIndentedln(
        baseTypeRefName != null
            ? 'return $baseTypeRefName.canParse(obj);'
            : 'return true;',
      )
      ..outdent()
      ..writeIndentedln('}');
  }

  /// Writes the Dart class for [type].
  void _writeClass(
    IndentableStringBuffer buffer,
    JsonType type,
    String name,
    Map<String, JsonType> classProperties,
    Map<String, JsonType> baseProperties,
    JsonType? baseType,
    JsonType? resolvedBaseType, {
    Map<String, String> additionalValues = const {},
  }) {
    _writeTypeDescription(buffer, type);

    // Types that are just aliases to simple value types should be written as
    // typedefs.
    if (type.isSimpleValue) {
      buffer.writeln('typedef $name = ${type.asDartType()};');
      return;
    }

    // Some properties are defined in both the base and the class, because the
    // type may be narrowed, but sometimes we only want those that are defined
    // only in this class.
    final classOnlyProperties = {
      for (final property in classProperties.entries)
        if (!baseProperties.containsKey(property.key))
          property.key: property.value,
    };
    buffer.write('class $name ');
    if (baseType != null) {
      buffer.write('extends ${baseType.refName} ');
    }
    buffer
      ..writeln('{')
      ..indent();
    for (final val in additionalValues.entries) {
      buffer
        ..writeIndentedln('@override')
        ..writeIndentedln("final ${val.key} = '${val.value}';");
    }
    _writeFields(buffer, type, classOnlyProperties);
    buffer.writeln();
    _writeFromJsonStaticMethod(buffer, name);
    buffer.writeln();
    _writeConstructor(buffer, name, type, classProperties, baseProperties,
        classOnlyProperties,
        baseType: resolvedBaseType);
    buffer.writeln();
    _writeFromMapConstructor(buffer, name, type, classOnlyProperties,
        callSuper: resolvedBaseType != null);
    buffer.writeln();
    _writeCanParseMethod(buffer, type, classProperties,
        baseTypeRefName: baseType?.refName);
    buffer.writeln();
    _writeToJsonMethod(buffer, name, type, classOnlyProperties,
        callSuper: resolvedBaseType != null);
    buffer
      ..outdent()
      ..writeln('}')
      ..writeln();
  }

  /// Write a map to look up the `command` for a given `RequestArguments` type
  /// to simplify sending requests back to the client:
  ///
  ///     this.sendRequest(FooArguments(x: 1))
  ///
  /// instead of
  ///
  ///     this.sendRequest(Request(
  ///       seq: seq++,
  ///       command: request.command,
  ///       arguments: {
  ///         x: 1
  ///         ...
  ///       }
  ///     ))
  void _writeCommandArgumentTypeLookup(
      IndentableStringBuffer buffer, JsonSchema schema) {
    buffer
      ..writeln('const commandTypes = {')
      ..indent();
    for (final entry in schema.definitions.entries.sortedBy((e) => e.key)) {
      final type = entry.value;
      final baseType = type.baseType;

      if (baseType?.refName == 'Request') {
        final classProperties = schema.propertiesFor(type);
        final argumentsProperty = classProperties['arguments'];
        final commandType = classProperties['command']?.literalValue;
        if (argumentsProperty?.dollarRef != null && commandType != null) {
          buffer.writeIndentedln(
              "${argumentsProperty!.refName}: '$commandType',");
        }
      }
    }
    buffer
      ..writeln('};')
      ..outdent();
  }

  /// Writes a constructor for [type].
  ///
  /// The constructor will have named arguments for all fields, with those that
  /// are mandatory marked with `required`.
  void _writeConstructor(
    IndentableStringBuffer buffer,
    String name,
    JsonType type,
    Map<String, JsonType> classProperties,
    Map<String, JsonType> baseProperties,
    Map<String, JsonType> classOnlyProperties, {
    required JsonType? baseType,
  }) {
    buffer.writeIndented('$name(');
    if (classProperties.isNotEmpty || baseProperties.isNotEmpty) {
      buffer
        ..writeln('{')
        ..indent();

      // Properties for this class are written as 'this.foo'.
      for (final entry in classOnlyProperties.entries.sortedBy((e) => e.key)) {
        final propertyName = entry.key;
        final fieldName = _dartSafeName(propertyName);
        final isOptional = !type.requiresField(propertyName);
        buffer.writeIndented('');
        if (!isOptional) {
          buffer.write('required ');
        }
        buffer.writeln('this.$fieldName, ');
      }

      // Properties from the base class are super-parameters.
      for (final entry in baseProperties.entries.sortedBy((e) => e.key)) {
        final propertyName = entry.key;
        // If this field is defined by the class and the base, prefer the
        // class one as it may contain things like the literal values.
        final propertyType = classProperties[propertyName] ?? entry.value;

        final fieldName = _dartSafeName(propertyName);
        if (propertyType.literalValue != null) {
          continue;
        }
        final isOptional = !type.requiresField(propertyName);
        buffer.writeIndented('');
        if (!isOptional) {
          buffer.write('required ');
        }
        buffer.writeln('super.$fieldName, ');
      }
      buffer
        ..outdent()
        ..writeIndented('}');
    }
    buffer.write(')');

    // We might still need an explicit super() call if we have literal values
    // to pass through.
    if (baseType != null) {
      final requiredExplicitSuperArgs = baseProperties.entries
          .map((entry) =>
              MapEntry(entry.key, classProperties[entry.key]?.literalValue))
          .where((entry) => entry.value != null)
          .toList();
      if (requiredExplicitSuperArgs.isNotEmpty) {
        buffer
          ..write(': super(')
          ..writeln()
          ..indent();
        for (final entry in requiredExplicitSuperArgs) {
          final name = entry.key;
          final value = entry.value;
          buffer.writeIndentedln('$name: \'$value\', ');
        }
        buffer
          ..outdent()
          ..writeIndented('')
          ..write(')');
      }
    }
    buffer.writeln(';');
  }

  /// Write a class for each item in the DAP spec.
  ///
  /// Skips over the Request and Event sub-classes, as they are handled by the
  /// simplified body classes written by [_writeBodyClasses]. Uses
  /// [RequestArguments] as the base class for all argument classes.
  void _writeDefinitionClasses(
      IndentableStringBuffer buffer, JsonSchema schema) {
    for (final entry in schema.definitions.entries.sortedBy((e) => e.key)) {
      final name = entry.key;
      final type = entry.value;

      var baseType = type.baseType;
      final resolvedBaseType =
          baseType != null ? schema.typeFor(baseType) : null;
      final classProperties = schema.propertiesFor(type, includeBase: false);
      final baseProperties = resolvedBaseType != null
          ? schema.propertiesFor(resolvedBaseType)
          : <String, JsonType>{};

      // Skip creation of Request sub-classes, as we don't use these we just
      // pass the arguments into the method directly.
      if (name != 'Request' && name.endsWith('Request')) {
        continue;
      }

      // Skip creation of Event sub-classes, as we don't use these we just
      // pass the body into sendEvent directly.
      if (name != 'Event' && name.endsWith('Event')) {
        continue;
      }

      // Create a synthetic base class for arguments to provide type safety
      // for sending requests.
      if (baseType == null && name.endsWith('Arguments')) {
        baseType = JsonType.named(schema, 'RequestArguments');
      }

      _writeClass(
        buffer,
        type,
        name,
        classProperties,
        baseProperties,
        baseType,
        resolvedBaseType,
      );
    }
  }

  /// Writes a DartDoc comment, wrapped at 80 characters taking into account
  /// the indentation.
  void _writeDescription(IndentableStringBuffer buffer, String? description) {
    final maxLength = 80 - buffer.totalIndent - 4;
    if (description != null) {
      for (final line in _wrapLines(description.split('\n'), maxLength)) {
        buffer.writeIndentedln('/// $line');
      }
    }
  }

  /// Write a map to look up the `event` for a given `EventBody` type
  /// to simplify sending events back to the client:
  ///
  ///     this.sendEvent(FooEvent(x: 1))
  ///
  /// instead of
  ///
  ///     this.sendEvent(Event(
  ///       seq: seq++,
  ///       event: 'FooEvent',
  ///       arguments: {
  ///         x: 1
  ///         ...
  ///       }
  ///     ))
  void _writeEventTypeLookup(IndentableStringBuffer buffer, JsonSchema schema) {
    buffer
      ..writeln('const eventTypes = {')
      ..indent();
    for (final entry in schema.definitions.entries.sortedBy((e) => e.key)) {
      final name = entry.key;
      final type = entry.value;
      final baseType = type.baseType;

      if (baseType?.refName == 'Event') {
        final classProperties = schema.propertiesFor(type);
        final eventType = classProperties['event']!.literalValue;
        buffer.writeIndentedln("${name}Body: '$eventType',");
      }
    }
    buffer
      ..writeln('};')
      ..outdent();
  }

  /// Writes Dart fields for [properties], taking into account whether they are
  /// required for [type].
  void _writeFields(IndentableStringBuffer buffer, JsonType type,
      Map<String, JsonType> properties) {
    for (final entry in properties.entries.sortedBy((e) => e.key)) {
      final propertyName = entry.key;
      final fieldName = _dartSafeName(propertyName);
      final propertyType = entry.value;
      final isOptional = !type.requiresField(propertyName);
      final dartType = propertyType.asDartType(isOptional: isOptional);
      _writeDescription(buffer, propertyType.description);
      buffer.writeIndentedln('final $dartType $fieldName;');
    }
  }

  /// Writes an expression to deserialize a [valueCode].
  ///
  /// If [type] represents a spec type, it's `fromJson` function will be called.
  /// If [type] is a [List], it will be mapped over this function again.
  /// If [type] is an union, the appropriate `canParse` functions will be used to
  ///   determine which `fromJson` function to call.
  void _writeFromJsonExpression(
      IndentableStringBuffer buffer, JsonType type, String valueCode,
      {bool isOptional = false}) {
    final baseType = type.aliasFor ?? type;
    final dartType = type.asDartType(isOptional: isOptional);
    final dartTypeNotNullable = type.asDartType();
    final nullOp = isOptional ? '?' : '';

    if (baseType.isAny || baseType.isSimple) {
      buffer.write(valueCode);
      if (dartType != 'Object?') {
        buffer.write(' as $dartType');
      }
    } else if (type.isList) {
      buffer.write('($valueCode as List$nullOp)$nullOp.map((item) => ');
      _writeFromJsonExpression(buffer, type.items!, 'item');
      buffer.write(').toList()');
    } else if (type.isUnion) {
      final types = type.unionTypes;

      // Write a check against each type, e.g.:
      // x is y ? new Either.tx(x) : (...)
      for (var i = 0; i < types.length; i++) {
        final isLast = i == types.length - 1;

        // For the last item, if we're optional we won't wrap if in a check, as
        // the constructor will only be called if canParse() returned true, so
        // it'll the only remaining option.
        if (!isLast || isOptional) {
          _writeTypeCheckCondition(buffer, types[i], valueCode,
              isOptional: false);
          buffer.write(' ? ');
        }
        buffer.write('$dartTypeNotNullable.t${i + 1}(');
        _writeFromJsonExpression(buffer, types[i], valueCode);
        buffer.write(')');

        if (!isLast) {
          buffer.write(' : ');
        } else if (isLast && isOptional) {
          buffer.write(' : null');
        }
      }
    } else if (type.isSpecType) {
      if (isOptional) {
        buffer.write('$valueCode == null ? null : ');
      }
      buffer.write(
          '$dartTypeNotNullable.fromJson($valueCode as Map<String, Object?>)');
    } else {
      throw 'Unable to type check $valueCode against $type';
    }
  }

  /// Writes a static `fromJson` method that converts an object into a spec type
  /// by calling its fromMap constructor.
  ///
  /// This is a helper method used as a tear-off since the constructor cannot be.
  void _writeFromJsonStaticMethod(
    IndentableStringBuffer buffer,
    String name,
  ) =>
      buffer.writeIndentedln(
          'static $name fromJson(Map<String, Object?> obj) => $name.fromMap(obj);');

  /// Writes a fromMap constructor to construct an object from a JSON map.
  void _writeFromMapConstructor(
    IndentableStringBuffer buffer,
    String name,
    JsonType type,
    Map<String, JsonType> properties, {
    bool callSuper = false,
  }) {
    buffer
      ..writeIndented('$name.fromMap(')
      ..write(callSuper ? 'super.obj' : 'Map<String, Object?> obj')
      ..write(')');
    if (properties.isNotEmpty || callSuper) {
      buffer
        ..writeln(':')
        ..indent();
      var isFirst = true;
      for (final entry in properties.entries.sortedBy((e) => e.key)) {
        if (isFirst) {
          isFirst = false;
        } else {
          buffer.writeln(',');
        }

        final propertyName = entry.key;
        final fieldName = _dartSafeName(propertyName);
        final propertyType = entry.value;
        final isOptional = !type.requiresField(propertyName);

        buffer.writeIndented('$fieldName = ');
        _writeFromJsonExpression(buffer, propertyType, "obj['$propertyName']",
            isOptional: isOptional);
      }
      if (callSuper) {
        if (!isFirst) {
          buffer.writeln(',');
        }
        buffer.writeIndented('super.fromMap()');
      }
      buffer.outdent();
    }
    buffer.writeln(';');
  }

  /// Writes a toJson method to construct a JSON map for this class, recursively
  /// calling through base classes.
  void _writeToJsonMethod(
    IndentableStringBuffer buffer,
    String name,
    JsonType type,
    Map<String, JsonType> properties, {
    bool callSuper = false,
  }) {
    if (callSuper) {
      buffer.writeIndentedln('@override');
    }
    buffer
      ..writeIndentedln('Map<String, Object?> toJson() => {')
      ..indent();
    if (callSuper) {
      buffer.writeIndentedln('...super.toJson(),');
    }
    for (final entry in properties.entries.sortedBy((e) => e.key)) {
      final propertyName = entry.key;
      final fieldName = _dartSafeName(propertyName);
      final isOptional = !type.requiresField(propertyName);
      buffer.writeIndented('');
      if (isOptional) {
        buffer.write('if ($fieldName != null) ');
      }
      buffer.writeln("'$propertyName': $fieldName, ");
    }
    buffer
      ..outdent()
      ..writeIndentedln('};');
  }

  /// Writes an expression that checks whether [valueCode] represents a [type].
  void _writeTypeCheckCondition(
      IndentableStringBuffer buffer, JsonType type, String valueCode,
      {required bool isOptional, bool invert = false}) {
    final baseType = type.aliasFor ?? type;
    final dartType = type.asDartType(isOptional: isOptional);

    // When the expression is inverted, invert the operators so the generated
    // code is easier to read.
    final opBang = invert ? '!' : '';
    final opTrue = invert ? 'false' : 'true';
    final opIs = invert ? 'is!' : 'is';
    final opEquals = invert ? '!=' : '==';
    final opAnd = invert ? '||' : '&&';
    final opOr = invert ? '&&' : '||';
    final opEvery = invert ? 'any' : 'every';

    if (baseType.isAny) {
      buffer.write(opTrue);
    } else if (dartType == 'Null') {
      buffer.write('$valueCode $opEquals null');
    } else if (baseType.isSimple) {
      buffer.write('$valueCode $opIs $dartType');
    } else if (type.isList) {
      buffer.write('($valueCode $opIs List');
      buffer.write(' $opAnd ($valueCode.$opEvery((item) => ');
      _writeTypeCheckCondition(buffer, type.items!, 'item',
          isOptional: false, invert: invert);
      buffer.write('))');
      buffer.write(')');
    } else if (type.isUnion) {
      final types = type.unionTypes;
      // To type check a union, we recursively check against each of its types.
      buffer.write('(');
      for (var i = 0; i < types.length; i++) {
        if (i != 0) {
          buffer.write(' $opOr ');
        }
        _writeTypeCheckCondition(buffer, types[i], valueCode,
            isOptional: false, invert: invert);
      }
      if (isOptional) {
        buffer.write(' $opOr $valueCode $opEquals null');
      }
      buffer.write(')');
    } else if (type.isSpecType) {
      buffer.write('$opBang${type.asDartType()}.canParse($valueCode)');
    } else {
      throw 'Unable to type check $valueCode against $type';
    }
  }

  /// Writes the description for [type], looking at the base type from the
  /// DAP spec if necessary.
  void _writeTypeDescription(IndentableStringBuffer buffer, JsonType type) {
    // In the DAP spec, many of the descriptions are on one of the allOf types
    // rather than the type itself.
    final description = type.description ??
        type.allOf
            ?.firstWhereOrNull((element) => element.description != null)
            ?.description;

    _writeDescription(buffer, description);
  }
}

/// A [StringBuffer] with support for indenting.
class IndentableStringBuffer extends StringBuffer {
  int _indentLevel = 0;
  final int _indentSpaces = 2;

  int get totalIndent => _indentLevel * _indentSpaces;
  String get _indentString => ' ' * totalIndent;

  void indent() => _indentLevel++;
  void outdent() => _indentLevel--;

  void writeIndented(Object obj) {
    write(_indentString);
    write(obj);
  }

  void writeIndentedln(Object obj) {
    write(_indentString);
    writeln(obj);
  }
}
