// Copyright (c) 2021, 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 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 {},
  }) {
    // 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,
    };
    _writeTypeDescription(buffer, type);
    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 standard arguments that will be
      // passed to a super() call.
      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);
        final dartType = propertyType.asDartType(isOptional: isOptional);
        buffer.writeIndented('');
        if (!isOptional) {
          buffer.write('required ');
        }
        buffer.writeln('$dartType $fieldName, ');
      }
      buffer
        ..outdent()
        ..writeIndented('}');
    }
    buffer.write(')');

    if (baseType != null) {
      buffer.write(': super(');
      if (baseProperties.isNotEmpty) {
        buffer
          ..writeln()
          ..indent();
        for (final entry in baseProperties.entries) {
          final propertyName = entry.key;
          // Skip any properties that have literal values defined by the base
          // as we won't need to supply them.
          if (entry.value.literalValue != null) {
            continue;
          }
          // 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);
          final literalValue = propertyType.literalValue;
          final value = literalValue != null ? "'$literalValue'" : fieldName;
          buffer.writeIndentedln('$fieldName: $value, ');
        }
        buffer
          ..outdent()
          ..writeIndented('');
      }
      buffer.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 in to 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 in to 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 deserialise 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 dartType = type.asDartType(isOptional: isOptional);
    final dartTypeNotNullable = type.asDartType();
    final nullOp = isOptional ? '?' : '';

    if (type.isAny || type.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(Map<String, Object?> obj)');
    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(obj)');
      }
      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 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 (type.isAny) {
      buffer.write(opTrue);
    } else if (dartType == 'Null') {
      buffer.write('$valueCode $opEquals null');
    } else if (type.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);
  }
}
