// Copyright (c) 2015, 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.

library generate_vm_service_java;

import 'package:markdown/markdown.dart';
import 'package:pub_semver/pub_semver.dart';

import '../common/generate_common.dart';
import '../common/parser.dart';
import '../common/src_gen_common.dart';
import 'src_gen_java.dart';

export 'src_gen_java.dart' show JavaGenerator;

const String servicePackage = 'org.dartlang.vm.service';

const List<String> simpleTypes = [
  'BigDecimal',
  'boolean',
  'int',
  'String',
  'double'
];

const vmServiceJavadoc = '''
{@link VmService} allows control of and access to information in a running
Dart VM instance.
<br/>
Launch the Dart VM with the arguments:
<pre>
--pause_isolates_on_start
--observe
--enable-vm-service=some-port
</pre>
where <strong>some-port</strong> is a port number of your choice
which this client will use to communicate with the Dart VM.
See https://dart.dev/tools/dart-vm for more details.
Once the VM is running, instantiate a new {@link VmService}
to connect to that VM via {@link VmService#connect(String)}
or {@link VmService#localConnect(int)}.
<br/>
{@link VmService} is not thread safe and should only be accessed from
a single thread. In addition, a given VM should only be accessed from
a single instance of {@link VmService}.
<br/>
Calls to {@link VmService} should not be nested.
More specifically, you should not make any calls to {@link VmService}
from within any {@link Consumer} method.
''';

late Api api;

/// Convert documentation references
/// from spec style of `className` to javadoc style {@link className}
String? convertDocLinks(String? doc) {
  if (doc == null) return null;
  var sb = StringBuffer();
  int start = 0;
  int end = doc.indexOf('[');
  while (end != -1) {
    sb.write(doc.substring(start, end));
    start = end;
    end = doc.indexOf(']', start);
    if (end == -1) break;
    if (end == start + 1) {
      sb.write('[]');
    } else {
      sb.write('{@link ');
      sb.write(doc.substring(start + 1, end));
      sb.write('}');
    }
    start = end + 1;
    end = doc.indexOf('[', start);
  }
  sb.write(doc.substring(start));
  return sb.toString();
}

String? _coerceRefType(String? typeName) {
  if (typeName == 'Class') typeName = 'ClassObj';
  if (typeName == 'Error') typeName = 'ErrorObj';
  if (typeName == 'Object') typeName = 'Obj';
  if (typeName == '@Object') typeName = 'ObjRef';
  if (typeName == 'Function') typeName = 'Func';
  if (typeName == '@Function') typeName = 'FuncRef';
  if (typeName!.startsWith('@')) typeName = '${typeName.substring(1)}Ref';
  if (typeName == 'string') typeName = 'String';
  if (typeName == 'bool') typeName = 'boolean';
  if (typeName == 'num') typeName = 'BigDecimal';
  if (typeName == 'map') typeName = 'Map';
  return typeName;
}

class Api extends Member with ApiParseUtil {
  int? serviceMajor;
  int? serviceMinor;
  String? serviceVersion;
  List<Method> methods = [];
  List<Enum?> enums = [];
  List<Type?> types = [];
  Map<String, List<String>> streamIdMap = {};
  final String scriptLocation;

  @override
  String? get docs => null;

  @override
  String get name => 'api';

  Api(this.scriptLocation);

  void addProperty(String typeName, String propertyName, {String? javadoc}) {
    var t = types.firstWhere((t) => t!.name == typeName)!;
    for (var f in t.fields) {
      if (f.name == propertyName) {
        print('$typeName already has $propertyName field');
        return;
      }
    }
    var f = TypeField(t, javadoc);
    f.name = propertyName;
    f.type = MemberType();
    f.type.types = [TypeRef('String')];
    t.fields.add(f);
    print('added $propertyName field to $typeName');
  }

  void generate(JavaGenerator gen) {
    _setFileHeader();

    // Set default value for unspecified property
    setDefaultValue('Instance', 'valueAsStringIsTruncated');
    setDefaultValue('InstanceRef', 'valueAsStringIsTruncated');

    // Hack to populate method argument docs
    for (var m in methods) {
      for (var a in m.args) {
        if (a.hasDocs) continue;
        var t = types.firstWhere((Type? t) => t!.name == a.type.name,
            orElse: () => null);
        if (t != null) {
          a.docs = t.docs;
          continue;
        }
        var e = enums.firstWhere((Enum? e) => e!.name == a.type.name,
            orElse: () => null);
        if (e != null) {
          a.docs = e.docs;
          continue;
        }
      }
    }

    gen.writeType('$servicePackage.VmService', scriptLocation,
        (TypeWriter writer) {
      writer.addImport('com.google.gson.JsonArray');
      writer.addImport('com.google.gson.JsonObject');
      writer.addImport('com.google.gson.JsonPrimitive');
      writer.addImport('java.util.List');

      writer.addImport('$servicePackage.consumer.*');
      writer.addImport('$servicePackage.element.*');
      writer.javadoc = vmServiceJavadoc;
      writer.superclassName = '$servicePackage.VmServiceBase';

      for (String streamId in streamIdMap.keys.toList()..sort()) {
        String alias = streamId.toUpperCase();
        while (alias.startsWith('_')) {
          alias = alias.substring(1);
        }
        writer.addField('${alias}_STREAM_ID', 'String',
            modifiers: 'public static final', value: '"$streamId"');
      }

      writer.addField('versionMajor', 'int',
          modifiers: 'public static final',
          value: '$serviceMajor',
          javadoc:
              'The major version number of the protocol supported by this client.');
      writer.addField('versionMinor', 'int',
          modifiers: 'public static final',
          value: '$serviceMinor',
          javadoc:
              'The minor version number of the protocol supported by this client.');
      for (var m in methods) {
        m.generateVmServiceMethod(writer);
        if (m.hasOptionalArgs) {
          m.generateVmServiceMethod(writer, includeOptional: true);
        }
      }

      writer.addMethod('forwardResponse', [
        JavaMethodArg('consumer', 'Consumer'),
        JavaMethodArg('responseType', 'String'),
        JavaMethodArg('json', 'JsonObject')
      ], (StatementWriter writer) {
        var generatedForwards = <String>{};

        var sorted = methods.toList()
          ..sort((m1, m2) {
            return m1.consumerTypeName.compareTo(m2.consumerTypeName);
          });
        for (var m in sorted) {
          if (generatedForwards.add(m.consumerTypeName)) {
            m.generateVmServiceForward(writer);
          }
        }
        writer.addLine('if (consumer instanceof ServiceExtensionConsumer) {');
        writer
            .addLine('  ((ServiceExtensionConsumer) consumer).received(json);');
        writer.addLine('  return;');
        writer.addLine('}');
        writer.addLine('logUnknownResponse(consumer, json);');
      }, modifiers: null, isOverride: true);

      writer.addMethod('convertMapToJsonObject', [
        JavaMethodArg('map', 'Map<String, String>')
      ], (StatementWriter writer) {
        writer.addLine('JsonObject obj = new JsonObject();');
        writer.addLine('for (String key : map.keySet()) {');
        writer.addLine('  obj.addProperty(key, map.get(key));');
        writer.addLine('}');
        writer.addLine('return obj;');
      }, modifiers: 'private', returnType: 'JsonObject');

      writer.addMethod(
          'convertIterableToJsonArray', [JavaMethodArg('list', 'Iterable')],
          (StatementWriter writer) {
        writer.addLine('JsonArray arr = new JsonArray();');
        writer.addLine('for (Object element : list) {');
        writer.addLine('  arr.add(new JsonPrimitive(element.toString()));');
        writer.addLine('}');
        writer.addLine('return arr;');
      }, modifiers: 'private', returnType: 'JsonArray');
    });

    for (var m in methods) {
      m.generateConsumerInterface(gen);
    }
    for (var t in types) {
      t!.generateElement(gen);
    }
    for (var e in enums) {
      e!.generateEnum(gen);
    }
  }

  Type? getType(String? name) =>
      types.firstWhere((t) => t!.name == name, orElse: () => null);

  bool isEnumName(String? typeName) =>
      enums.any((Enum? e) => e!.name == typeName);

  void parse(List<Node> nodes) {
    Version version = ApiParseUtil.parseVersionSemVer(nodes);
    serviceMajor = version.major;
    serviceMinor = version.minor;
    serviceVersion = '$serviceMajor.$serviceMinor';

    // Look for h3 nodes
    // the pre following it is the definition
    // the optional p following that is the documentation

    String? h3Name;

    // TODO(helin24): This code does not capture documentation with more than
    //  one paragraph or lists. It may help to check generate_dart to fix this.
    for (int i = 0; i < nodes.length; i++) {
      Node node = nodes[i];

      if (isPre(node) && h3Name != null) {
        String definition = textForCode(node)
            .replaceAll('(string|Null)', 'string'); // this is terrible.
        String? docs;

        if (i + 1 < nodes.length && isPara(nodes[i + 1])) {
          Element p = nodes[++i] as Element;
          docs = collapseWhitespace(TextOutputVisitor.printText(p));
        }

        _parse(h3Name, definition, docs);
      } else if (isH3(node)) {
        h3Name = textForElement(node);
      } else if (isHeader(node)) {
        h3Name = null;
      } else if (isPara(node)) {
        var children = (node as Element).children!;
        if (children.isNotEmpty && children.first is Text) {
          var text = children.expand<String>((child) {
            if (child is Text) return [child.text];
            return [];
          }).join();
          if (text.startsWith('streamId |')) {
            _parseStreamIds(text);
          }
        }
      }
    }
    for (Type? type in types) {
      type!.calculateFieldOverrides();
    }
  }

  void setDefaultValue(String typeName, String propertyName) {
    var type = types.firstWhere((t) => t!.name == typeName)!;
    var field = type.fields.firstWhere((f) => f.name == propertyName);
    field.defaultValue = 'false';
  }

  void _parse(String name, String definition, [String? docs]) {
    name = replaceHTMLEntities(name.trim());
    definition = replaceHTMLEntities(definition.trim());
    if (docs != null) docs = replaceHTMLEntities(docs.trim());

    if (definition.startsWith('class ')) {
      types.add(Type(this, scriptLocation, name, definition, docs));
    } else if (name.substring(0, 1).toLowerCase() == name.substring(0, 1)) {
      methods.add(Method(name, scriptLocation, definition, docs));
    } else if (definition.startsWith('enum ')) {
      enums.add(Enum(name, scriptLocation, definition, docs));
    } else {
      throw 'unexpected entity: $name, $definition';
    }
  }

  void _parseStreamIds(String text) {
    for (String line in text.split('\n')) {
      if (line.startsWith('streamId |')) continue;
      if (line.startsWith('---')) continue;
      var index = line.indexOf('|');
      var streamId = line.substring(0, index).trim();
      List<String> eventTypes =
          List.from(line.substring(index + 1).split(',').map((t) => t.trim()));
      eventTypes.sort();
      streamIdMap[streamId] = eventTypes;
    }
  }

  void _setFileHeader() {
    fileHeader = r'''/*
 * Copyright (c) 2015, the Dart project authors.
 *
 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
''';
  }

  static String printNode(Node n) {
    if (n is Text) {
      return n.text;
    } else if (n is Element) {
      if (n.tag != 'h3') return n.tag;
      return '${n.tag}:[${n.children!.map((c) => printNode(c)).join(', ')}]';
    } else {
      return '$n';
    }
  }
}

class Enum extends Member {
  @override
  final String name;
  final String scriptLocation;
  @override
  final String? docs;

  List<EnumValue> enums = [];

  Enum(this.name, this.scriptLocation, String definition, [this.docs]) {
    _parse(Tokenizer(definition).tokenize());
  }

  String get elementTypeName => '$servicePackage.element.$name';

  void generateEnum(JavaGenerator gen) {
    gen.writeType(elementTypeName, scriptLocation, (TypeWriter writer) {
      writer.javadoc = convertDocLinks(docs);
      writer.isEnum = true;
      enums.sort((v1, v2) => v1.name!.compareTo(v2.name!));
      for (var value in enums) {
        writer.addEnumValue(value.name, javadoc: value.docs);
      }
      writer.addEnumValue('Unknown',
          javadoc: 'Represents a value returned by the VM'
              ' but unknown to this client.',
          isLast: true);
    });
  }

  void _parse(Token? token) {
    EnumParser(token).parseInto(this);
  }
}

class EnumParser extends Parser {
  EnumParser(super.startToken);

  void parseInto(Enum e) {
    // enum ErrorKind { UnhandledException, Foo, Bar }
    // enum name { (comment* name ,)+ }
    expect('enum');

    Token t = expectName();
    validate(t.text == e.name, 'enum name ${e.name} equals ${t.text}');
    expect('{');

    while (!t.eof) {
      if (consume('}')) break;
      String? docs = collectComments();
      t = expectName();
      consume(',');

      e.enums.add(EnumValue(e, t.text, docs));
    }
  }
}

class EnumValue extends Member {
  final Enum parent;
  @override
  final String? name;
  @override
  final String? docs;

  EnumValue(this.parent, this.name, [this.docs]);

  bool get isLast => parent.enums.last == this;
}

abstract class Member {
  String? get docs => null;

  bool get hasDocs => docs != null;

  String? get name;

  @override
  String toString() => name!;
}

class MemberType extends Member {
  List<TypeRef> types = [];

  MemberType();

  bool get hasSentinel => types.any((t) => t.name == 'Sentinel');

  bool get isEnum => types.length == 1 && api.isEnumName(types.first.name);

  bool get isMultipleReturns => types.length > 1;

  List<TypeRef> get subsetOfTypesThatAreSimple =>
      types.where((TypeRef typeRef) => typeRef.isSimple).toList();

  List<TypeRef> get subsetOfTypesThatAreNotSimple =>
      types.where((TypeRef typeRef) => !typeRef.isSimple).toList();

  bool get isSimple => types.length == 1 && types.first.isSimple;

  bool get isValueAndSentinel => types.length == 2 && hasSentinel;

  @override
  String? get name {
    if (types.isEmpty) return '';
    if (types.length == 1) return types.first.ref;
    return 'dynamic';
  }

  TypeRef? get valueType {
    if (types.length == 1) return types.first;
    if (isValueAndSentinel) {
      return types.firstWhere((t) => t.name != 'Sentinel');
    }
    return null;
  }

  void parse(Parser parser) {
    // foo|bar[]|baz
    // (@Instance|Sentinel)[]
    bool loop = true;
    bool isMulti = false;

    while (loop) {
      parser.consume('(');
      Token t = parser.expectName();
      if (parser.consume(')')) isMulti = true;
      TypeRef ref = TypeRef(_coerceRefType(t.text));
      types.add(ref);

      while (parser.consume('[')) {
        parser.expect(']');
        if (isMulti) {
          for (var t in types) {
            t.arrayDepth++;
          }
        } else {
          ref.arrayDepth++;
        }
      }

      loop = parser.consume('|');
    }
  }
}

class Method extends Member {
  @override
  final String name;
  final String scriptLocation;
  @override
  final String? docs;

  MemberType returnType = MemberType();
  bool deprecated = false;
  List<MethodArg> args = [];

  Method(this.name, this.scriptLocation, String definition, [this.docs]) {
    _parse(Tokenizer(definition).tokenize());
  }

  String get consumerTypeName {
    String? prefix;
    if (returnType.isMultipleReturns) {
      prefix = titleCase(name);
    } else {
      prefix = returnType.types.first.javaBoxedName;
    }
    return '$servicePackage.consumer.${prefix}Consumer';
  }

  bool get hasArgs => args.isNotEmpty;

  bool get hasOptionalArgs => args.any((MethodArg arg) => arg.optional);

  void generateConsumerInterface(JavaGenerator gen) {
    gen.writeType(consumerTypeName, scriptLocation, (TypeWriter writer) {
      writer.javadoc = convertDocLinks(returnType.docs);
      writer.interfaceNames.add('$servicePackage.consumer.Consumer');
      writer.isInterface = true;
      for (var t in returnType.types) {
        writer.addImport(t.elementTypeName);
        writer.addMethod(
            'received', [JavaMethodArg('response', t.elementTypeName)], null);
      }
    });
  }

  void generateVmServiceForward(StatementWriter writer) {
    var consumerName = classNameFor(consumerTypeName);
    writer.addLine('if (consumer instanceof $consumerName) {');
    List<Type?> types = List.from(returnType.types.map((ref) => ref.type));
    for (int index = 0; index < types.length; ++index) {
      types.addAll(types[index]!.subtypes);
    }
    types.sort((t1, t2) => t1!.name!.compareTo(t2!.name!));
    for (var t in types) {
      var responseName = classNameFor(t!.elementTypeName!);
      writer.addLine('  if (responseType.equals("${t.rawName}")) {');
      writer.addLine(
          '    (($consumerName) consumer).received(new $responseName(json));');
      writer.addLine('    return;');
      writer.addLine('  }');
    }
    writer.addLine('}');
  }

  void generateVmServiceMethod(TypeWriter writer, {includeOptional = false}) {
    // Update method docs
    var javadoc = StringBuffer(docs == null ? '' : docs!);
    bool firstParamDoc = true;
    for (var a in args) {
      if (!includeOptional && a.optional) continue;
      var paramDoc = StringBuffer(a.docs ?? '');
      if (paramDoc.isEmpty) {}
      if (a.optional) {
        if (paramDoc.isNotEmpty) paramDoc.write(' ');
        paramDoc.write('This parameter is optional and may be null.');
      }
      if (paramDoc.isNotEmpty) {
        if (firstParamDoc) {
          javadoc.writeln();
          firstParamDoc = false;
        }
        javadoc.writeln('@param ${a.name} $paramDoc');
      }
    }

    if (args.any((MethodArg arg) => (arg.type.name == 'Map'))) {
      writer.addImport('java.util.Map');
    }

    List<MethodArg> mthArgs = args;
    if (!includeOptional) {
      mthArgs = mthArgs.toList()..removeWhere((a) => a.optional);
    }

    List<JavaMethodArg> javaMethodArgs =
        List.from(mthArgs.map((a) => a.asJavaMethodArg));
    javaMethodArgs
        .add(JavaMethodArg('consumer', classNameFor(consumerTypeName)));
    writer.addMethod(name, javaMethodArgs, (StatementWriter writer) {
      writer.addLine('final JsonObject params = new JsonObject();');
      for (MethodArg arg in args) {
        if (!includeOptional && arg.optional) continue;
        var argName = arg.name;
        String op = arg.optional ? 'if ($argName != null) ' : '';
        if (arg.isEnumType) {
          writer
              .addLine('${op}params.addProperty("$argName", $argName.name());');
        } else if (arg.type.name == 'Map') {
          writer.addLine(
              '${op}params.add("$argName", convertMapToJsonObject($argName));');
        } else if (arg.type.arrayDepth > 0) {
          writer.addLine(
              '${op}params.add("$argName", convertIterableToJsonArray($argName));');
        } else if (name.startsWith('evaluate') && argName == 'expression') {
          // Special case the eval expression parameters.
          writer.addLine(
              '${op}params.addProperty("$argName", removeNewLines($argName));');
        } else {
          writer.addLine('${op}params.addProperty("$argName", $argName);');
        }
      }
      writer.addLine('request("$name", params, consumer);');
    }, javadoc: javadoc.toString(), isDeprecated: deprecated);
  }

  void _parse(Token? token) {
    MethodParser(token).parseInto(this);
  }
}

class MethodArg extends Member {
  final Method parent;
  final TypeRef type;
  @override
  String? name;
  @override
  String? docs;
  bool optional = false;

  MethodArg(this.parent, this.type, this.name);

  JavaMethodArg get asJavaMethodArg {
    if (optional && type.ref == 'int') {
      return JavaMethodArg(name, 'Integer');
    }
    if (optional && type.ref == 'double') {
      return JavaMethodArg(name, 'Double');
    }
    if (optional && type.ref == 'boolean') {
      return JavaMethodArg(name, 'Boolean');
    }
    return JavaMethodArg(name, type.ref);
  }

  /// TODO: Hacked enum arg type determination
  bool get isEnumType =>
      name == 'step' || name == 'mode' || name == 'exceptionPauseMode';
}

class MethodParser extends Parser {
  MethodParser(super.startToken);

  void parseInto(Method method) {
    // method is return type, name, (, args )
    // args is type name, [optional], comma

    if (peek()?.text?.startsWith('@deprecated') ?? false) {
      advance();
      expect('(');
      consumeString();
      expect(')');
      method.deprecated = true;
    }
    method.returnType.parse(this);

    Token t = expectName();
    validate(
        t.text == method.name, 'method name ${method.name} equals ${t.text}');

    expect('(');

    while (peek()!.text != ')') {
      Token type = expectName();
      TypeRef ref = TypeRef(_coerceRefType(type.text));
      if (peek()!.text == '[') {
        while (consume('[')) {
          expect(']');
          ref.arrayDepth++;
        }
      } else if (peek()!.text == '<') {
        // handle generics
        expect('<');
        ref.genericTypes = [];
        while (peek()!.text != '>') {
          Token genericTypeName = expectName();
          ref.genericTypes!.add(TypeRef(_coerceRefType(genericTypeName.text)));
          consume(',');
        }
        expect('>');
      }
      Token name = expectName();
      MethodArg arg = MethodArg(method, ref, name.text);
      if (consume('[')) {
        expect('optional');
        expect(']');
        arg.optional = true;
      }
      method.args.add(arg);
      consume(',');
    }

    expect(')');
  }
}

class TextOutputVisitor implements NodeVisitor {
  StringBuffer buf = StringBuffer();

  bool _inRef = false;

  TextOutputVisitor();

  @override
  String toString() => buf.toString().trim();

  @override
  bool visitElementBefore(Element element) {
    if (element.tag == 'em') {
      buf.write('[');
      _inRef = true;
    } else if (element.tag == 'p') {
      // Nothing to do.
    } else if (element.tag == 'a') {
      // Nothing to do - we're not writing out <a> refs (they won't resolve).
    } else if (element.tag == 'code') {
      buf.write(renderToHtml([element]));
    } else {
      print('unknown tag: ${element.tag}');
      buf.write(renderToHtml([element]));
    }

    return true;
  }

  @override
  void visitText(Text text) {
    String? t = text.text;
    if (_inRef) t = _coerceRefType(t);
    buf.write(t);
  }

  @override
  void visitElementAfter(Element element) {
    if (element.tag == 'em') {
      buf.write(']');
      _inRef = false;
    } else if (element.tag == 'p') {
      buf.write('\n\n');
    }
  }

  static String printText(Node node) {
    TextOutputVisitor visitor = TextOutputVisitor();
    node.accept(visitor);
    return visitor.toString();
  }
}

class Type extends Member {
  final Api parent;
  final String scriptLocation;
  String? rawName;
  @override
  String? name;
  String? superName;
  @override
  final String? docs;
  List<TypeField> fields = [];

  Type(this.parent, this.scriptLocation, String categoryName, String definition,
      [this.docs]) {
    _parse(Tokenizer(definition).tokenize());
  }

  String? get elementTypeName {
    if (isSimple) return null;
    return '$servicePackage.element.$name';
  }

  bool get isRef => name!.endsWith('Ref');

  bool get isResponse {
    if (superName == null) return false;
    if (name == 'Response' || superName == 'Response') return true;
    return parent.getType(superName)!.isResponse;
  }

  bool get isSimple => simpleTypes.contains(name);

  String? get jsonTypeName {
    if (name == 'ClassObj') return 'Class';
    if (name == 'ErrorObj') return 'Error';
    return name;
  }

  Iterable<Type?> get subtypes =>
      api.types.toList()..retainWhere((t) => t!.superName == name);

  void generateElement(JavaGenerator gen) {
    gen.writeType('$servicePackage.element.$name', scriptLocation,
        (TypeWriter writer) {
      if (fields.any((f) => f.type.types.any((t) => t.isArray))) {
        writer.addImport('com.google.gson.JsonObject');
      }
      writer.addImport('com.google.gson.JsonObject');
      writer.javadoc = convertDocLinks(docs);
      writer.superclassName = superName ?? 'Element';
      writer.addConstructor(
          <JavaMethodArg>[JavaMethodArg('json', 'com.google.gson.JsonObject')],
          (StatementWriter writer) {
        writer.addLine('super(json);');
      });

      if (name == 'InstanceRef' || name == 'Instance') {
        writer.addMethod(
          'isNull',
          [],
          (StatementWriter writer) {
            writer.addLine('return getKind() == InstanceKind.Null;');
          },
          returnType: 'boolean',
          javadoc: 'Returns whether this instance represents null.',
        );
      }

      for (var field in fields) {
        field.generateAccessor(writer);
      }
    });
  }

  List<TypeField> getAllFields() {
    if (superName == null) return fields;

    List<TypeField> all = [];
    all.insertAll(0, fields);

    Type? s = getSuper();
    while (s != null) {
      all.insertAll(0, s.fields);
      s = s.getSuper();
    }

    return all;
  }

  Type? getSuper() => superName == null ? null : api.getType(superName);

  bool hasField(String? name) {
    if (fields.any((field) => field.name == name)) return true;
    return getSuper()?.hasField(name) ?? false;
  }

  void _parse(Token? token) {
    TypeParser(token).parseInto(this);
  }

  void calculateFieldOverrides() {
    for (TypeField field in fields.toList()) {
      if (superName == null) continue;

      if (getSuper()!.hasField(field.name)) {
        field.setOverrides();
      }
    }
  }
}

// @Instance|@Error|Sentinel evaluate(
//     string isolateId,
//     string targetId [optional],
//     string expression)
class TypeField extends Member {
  static final Map<String, String> _nameRemap = {
    'const': 'isConst',
    'final': 'isFinal',
    'static': 'isStatic',
    'abstract': 'isAbstract',
    'super': 'superClass',
    'class': 'classRef'
  };

  final Type parent;
  final String? _docs;
  MemberType type = MemberType();
  @override
  String? name;
  bool optional = false;
  String? defaultValue;
  bool overrides = false;

  TypeField(this.parent, this._docs);

  void setOverrides() {
    overrides = true;
  }

  String get accessorName {
    var remappedName = _nameRemap[name];
    if (remappedName != null) {
      if (remappedName.startsWith('is')) return remappedName;
    } else {
      remappedName = name;
    }
    return 'get${titleCase(remappedName!)}';
  }

  @override
  String? get docs {
    String str = _docs == null ? '' : _docs!;
    if (type.isMultipleReturns) {
      str += '\n\n@return one of '
          '${joinLast(type.types.map((t) => '<code>$t</code>'), ', ', ' or ')}';
      str = str.trim();
    }
    if (optional) {
      str += '\n\nCan return <code>null</code>.';
      str = str.trim();
    }
    return str;
  }

  void generateAccessor(TypeWriter writer) {
    if (type.isMultipleReturns && !type.isValueAndSentinel) {
      writer.addMethod(accessorName, [], (StatementWriter w) {
        w.addImport('com.google.gson.JsonElement');
        w.addLine('final JsonElement elem = json.get("$name");');
        w.addLine('if (elem == null) return null;\n');
        final subsetOfTypesThatAreSimple = type.subsetOfTypesThatAreSimple;
        final subsetOfTypesThatAreNotSimple =
            type.subsetOfTypesThatAreNotSimple;
        if (subsetOfTypesThatAreSimple.isNotEmpty) {
          w.addImport('com.google.gson.JsonPrimitive');
          w.addLine('if (elem.isJsonPrimitive()) {');
          w.addLine('final JsonPrimitive p = (JsonPrimitive) elem;');
          for (TypeRef t in subsetOfTypesThatAreSimple) {
            if (t.name == 'boolean') {
              w.addLine('if (p.isBoolean()) return p.getAsBoolean();');
            } else if (t.name == 'int') {
              w.addLine('if (p.isNumber()) return p.getAsInt();');
            } else if (t.name == 'String') {
              w.addLine('if (p.isString()) return p.getAsString();');
            }
          }
          w.addLine('}');
        }
        if (subsetOfTypesThatAreNotSimple.isNotEmpty) {
          w.addImport('com.google.gson.JsonObject');
          w.addLine('if (elem.isJsonObject()) {');
          w.addLine('final JsonObject o = (JsonObject) elem;');
          for (TypeRef t in subsetOfTypesThatAreNotSimple) {
            String refName = t.name!;
            if (refName.endsWith('Ref')) {
              refName = '@${refName.substring(0, refName.length - 3)}';
            }
            w.addLine('if (o.get("type").getAsString().equals("$refName")) '
                'return new ${t.name}(o);');
          }
          w.addLine('}');
        }
        w.addLine('return null;');
      }, javadoc: docs, returnType: 'Object');
    } else {
      String? returnType = type.valueType!.ref;
      if (name == 'timestamp') {
        returnType = 'long';
      }

      writer.addMethod(
        accessorName,
        [],
        (StatementWriter writer) {
          type.valueType!.generateAccessStatements(
            writer,
            name,
            canBeSentinel: type.isValueAndSentinel,
            defaultValue: defaultValue,
            optional: optional,
          );
        },
        javadoc: docs,
        returnType: returnType,
        isOverride: overrides,
      );
    }
  }
}

class TypeParser extends Parser {
  TypeParser(super.startToken);

  void parseInto(Type type) {
    // class ClassList extends Response {
    //   // Docs here.
    //   @Class[] classes [optional];
    // }
    expect('class');

    Token t = expectName();
    type.rawName = t.text;
    type.name = _coerceRefType(type.rawName);
    if (consume('extends')) {
      t = expectName();
      type.superName = _coerceRefType(t.text);
    }

    expect('{');

    while (peek()!.text != '}') {
      TypeField field = TypeField(type, collectComments());
      field.type.parse(this);
      field.name = expectName().text;
      if (consume('[')) {
        expect('optional');
        expect(']');
        field.optional = true;
      }
      type.fields.add(field);
      expect(';');
    }

    expect('}');
  }
}

class TypeRef {
  String? name;
  int arrayDepth = 0;
  List<TypeRef>? genericTypes;

  TypeRef(this.name);

  String? get elementTypeName {
    if (isSimple) return null;
    return '$servicePackage.element.$name';
  }

  bool get isArray => arrayDepth > 0;

  /// Hacked enum determination
  bool get isEnum => name!.endsWith('Kind') || name!.endsWith('Mode');

  bool get isSimple => simpleTypes.contains(name);

  String? get javaBoxedName {
    if (name == 'boolean') return 'Boolean';
    if (name == 'int') return 'Integer';
    if (name == 'double') return 'Double';
    return name;
  }

  String? get ref {
    if (genericTypes != null) {
      return '$name<${genericTypes!.join(', ')}>';
    } else if (isSimple) {
      if (arrayDepth == 2) return 'List<List<$javaBoxedName>>';
      if (arrayDepth == 1) return 'List<$javaBoxedName>';
    } else {
      if (arrayDepth == 2) return 'ElementList<ElementList<$javaBoxedName>>';
      if (arrayDepth == 1) return 'ElementList<$javaBoxedName>';
    }
    return name;
  }

  Type? get type => api.types.firstWhere((t) => t!.name == name);

  void generateAccessStatements(
    StatementWriter writer,
    String? propertyName, {
    bool canBeSentinel = false,
    String? defaultValue,
    bool optional = false,
  }) {
    if (name == 'boolean') {
      if (isArray) {
        print('skipped accessor body for $propertyName');
      } else {
        if (defaultValue != null) {
          writer.addImport('com.google.gson.JsonElement');
          writer.addLine('final JsonElement elem = json.get("$propertyName");');
          writer.addLine(
              'return elem != null ? elem.getAsBoolean() : $defaultValue;');
        } else {
          writer.addLine('return getAsBoolean("$propertyName");');
        }
      }
    } else if (name == 'int') {
      if (arrayDepth > 1) {
        writer.addImport('java.util.List');
        writer.addLine('return getListListInt("$propertyName");');
      } else if (arrayDepth == 1) {
        writer.addImport('java.util.List');
        writer.addLine('return getListInt("$propertyName");');
      } else {
        if (propertyName == 'timestamp') {
          writer.addLine('return json.get("$propertyName") == null ? '
              '-1 : json.get("$propertyName").getAsLong();');
        } else {
          writer.addLine('return getAsInt("$propertyName");');
        }
      }
    } else if (name == 'double') {
      writer.addLine('return json.get("$propertyName") == null ? '
          '0.0 : json.get("$propertyName").getAsDouble();');
    } else if (name == 'BigDecimal') {
      if (isArray) {
        print('skipped accessor body for $propertyName');
      } else {
        writer.addImport('java.math.BigDecimal');
        writer.addLine('return json.get("$propertyName").getAsBigDecimal();');
      }
    } else if (name == 'String') {
      if (isArray) {
        writer.addImport('java.util.List');
        if (optional) {
          writer.addLine('return json.get("$propertyName") == null ? '
              'null : getListString("$propertyName");');
        } else {
          writer.addLine('return getListString("$propertyName");');
        }
      } else {
        writer.addLine('return getAsString("$propertyName");');
      }
    } else if (isEnum) {
      if (isArray) {
        print('skipped accessor body for $propertyName');
      } else {
        if (optional) {
          writer.addLine('if (json.get("$propertyName") == null) return null;');
          writer.addLine('');
        }
        writer.addImport('com.google.gson.JsonElement');
        writer.addLine('final JsonElement value = json.get("$propertyName");');
        writer.addLine('try {');
        writer.addLine('  return value == null ? $name.Unknown'
            ' : $name.valueOf(value.getAsString());');
        writer.addLine('} catch (IllegalArgumentException e) {');
        writer.addLine('  return $name.Unknown;');
        writer.addLine('}');
      }
    } else {
      if (arrayDepth > 1) {
        print('skipped accessor body for $propertyName');
      } else if (arrayDepth == 1) {
        writer.addImport('com.google.gson.JsonArray');
        if (optional) {
          writer.addLine('if (json.get("$propertyName") == null) return null;');
          writer.addLine('');
        }
        writer.addLine(
            'return new ElementList<$javaBoxedName>(json.get("$propertyName").getAsJsonArray()) {');
        writer.addLine('  @Override');
        writer.addLine(
            '  protected $javaBoxedName basicGet(JsonArray array, int index) {');
        writer.addLine(
            '    return new $javaBoxedName(array.get(index).getAsJsonObject());');
        writer.addLine('  }');
        writer.addLine('};');
      } else {
        if (canBeSentinel) {
          writer.addImport('com.google.gson.JsonElement');
          writer.addLine('final JsonElement elem = json.get("$propertyName");');
          writer.addLine('if (!elem.isJsonObject()) return null;');
          writer.addLine('final JsonObject child = elem.getAsJsonObject();');
          writer
              .addLine('final String type = child.get("type").getAsString();');
          writer.addLine('if ("Sentinel".equals(type)) return null;');
          writer.addLine('return new $name(child);');
        } else {
          if (optional) {
            writer.addLine(
                'JsonObject obj = (JsonObject) json.get("$propertyName");');
            writer.addLine('if (obj == null) return null;');
            if ((name != 'InstanceRef') && (name != 'Instance')) {
              writer.addLine(
                  'final String type = json.get("type").getAsString();');
              writer.addLine(
                  'if ("Instance".equals(type) || "@Instance".equals(type)) {');
              writer.addLine(
                  '  final String kind = json.get("kind").getAsString();');
              writer.addLine('  if ("Null".equals(kind)) return null;');
              writer.addLine('}');
            }
            writer.addLine('return new $name(obj);');
          } else {
            writer.addLine(
                'return new $name((JsonObject) json.get("$propertyName"));');
          }
        }
      }
    }
  }

  @override
  String toString() => ref!;
}
