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

/// Data structures representing an API definition, and visitor base classes
/// for visiting those data structures.
import 'dart:collection';

import 'package:html/dom.dart' as dom;

/// Toplevel container for the API.
class Api extends ApiNode {
  final String version;
  final List<Domain> domains;
  final Types types;
  final Refactorings? refactorings;

  Api(this.version, this.domains, this.types, this.refactorings,
      dom.Element html,
      {bool? experimental})
      : super(html, experimental, false);
}

/// Base class for objects in the API model.
class ApiNode {
  /// A flag to indicate if this API is experimental.
  final bool experimental;

  /// A flag to indicate if this API is deprecated.
  final bool deprecated;

  /// Html element representing this part of the API.
  final dom.Element? html;

  ApiNode(this.html, bool? experimental, bool? deprecated)
      : experimental = experimental ?? false,
        deprecated = deprecated ?? false;
}

/// Base class for visiting the API definition.
abstract class ApiVisitor<T> {
  /// Dispatch the given [type] to the visitor.
  T visitTypeDecl(TypeDecl type) => type.accept(this);
  T visitTypeEnum(TypeEnum typeEnum);
  T visitTypeList(TypeList typeList);
  T visitTypeMap(TypeMap typeMap);
  T visitTypeObject(TypeObject typeObject);
  T visitTypeReference(TypeReference typeReference);

  T visitTypeUnion(TypeUnion typeUnion);
}

/// Definition of a single domain.
class Domain extends ApiNode {
  final String name;
  final List<Request> requests;
  final List<Notification> notifications;

  Domain(this.name, this.requests, this.notifications, dom.Element html,
      {bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);
}

/// API visitor that visits the entire API hierarchically by default.
class HierarchicalApiVisitor extends ApiVisitor {
  /// The API to visit.
  final Api api;

  HierarchicalApiVisitor(this.api);

  /// If [type] is a [TypeReference] that is defined in the API, follow the
  /// chain until a non-[TypeReference] is found, if possible.
  ///
  /// If it is not possible (because the chain ends with a [TypeReference] that
  /// is not defined in the API), then that final [TypeReference] is returned.
  TypeDecl? resolveTypeReferenceChain(TypeDecl? type) {
    while (type is TypeReference && api.types.containsKey(type.typeName)) {
      type = api.types[type.typeName]?.type;
    }
    return type;
  }

  void visitApi() {
    api.domains.forEach(visitDomain);
    visitTypes(api.types);
    visitRefactorings(api.refactorings);
  }

  void visitDomain(Domain domain) {
    domain.requests.forEach(visitRequest);
    domain.notifications.forEach(visitNotification);
  }

  void visitNotification(Notification notification) {
    if (notification.params != null) {
      visitTypeDecl(notification.params!);
    }
  }

  void visitRefactoring(Refactoring refactoring) {
    if (refactoring.feedback != null) {
      visitTypeDecl(refactoring.feedback!);
    }
    if (refactoring.options != null) {
      visitTypeDecl(refactoring.options!);
    }
  }

  void visitRefactorings(Refactorings? refactorings) {
    refactorings?.forEach(visitRefactoring);
  }

  void visitRequest(Request request) {
    if (request.params != null) {
      visitTypeDecl(request.params!);
    }
    if (request.result != null) {
      visitTypeDecl(request.result!);
    }
  }

  void visitTypeDefinition(TypeDefinition typeDefinition) {
    visitTypeDecl(typeDefinition.type);
  }

  @override
  void visitTypeEnum(TypeEnum typeEnum) {
    typeEnum.values.forEach(visitTypeEnumValue);
  }

  void visitTypeEnumValue(TypeEnumValue typeEnumValue) {}

  @override
  void visitTypeList(TypeList typeList) {
    visitTypeDecl(typeList.itemType);
  }

  @override
  void visitTypeMap(TypeMap typeMap) {
    visitTypeDecl(typeMap.keyType);
    visitTypeDecl(typeMap.valueType);
  }

  @override
  void visitTypeObject(TypeObject typeObject) {
    typeObject.fields.forEach(visitTypeObjectField);
  }

  void visitTypeObjectField(TypeObjectField typeObjectField) {
    visitTypeDecl(typeObjectField.type);
  }

  @override
  void visitTypeReference(TypeReference typeReference) {}

  void visitTypes(Types types) {
    types.forEach(visitTypeDefinition);
  }

  @override
  void visitTypeUnion(TypeUnion typeUnion) {
    typeUnion.choices.forEach(visitTypeDecl);
  }
}

/// Description of a notification method.
class Notification extends ApiNode {
  /// Name of the domain enclosing this request.
  final String domainName;

  /// Name of the notification, without the domain prefix.
  final String event;

  /// Type of the object associated with the "params" key in the notification
  /// object, or null if the notification has no parameters.
  final TypeObject? params;

  Notification(this.domainName, this.event, this.params, dom.Element html,
      {bool? experimental})
      : super(html, experimental, false);

  /// Get the name of the notification, including the domain prefix.
  String get longEvent => '$domainName.$event';

  /// Get the full type of the notification object, including the common "id"
  /// and "error" fields.
  TypeDecl get notificationType {
    var fields = <TypeObjectField>[
      TypeObjectField('event', TypeReference('String', null), null,
          value: '$domainName.$event')
    ];
    if (params != null) {
      fields.add(TypeObjectField('params', params!, null));
    }
    return TypeObject(fields, null);
  }
}

/// Description of a single refactoring.
class Refactoring extends ApiNode {
  /// Name of the refactoring. This should match one of the values allowed for
  /// RefactoringKind.
  final String kind;

  /// Type of the refactoring feedback, or null if the refactoring has no
  /// feedback.
  final TypeObject? feedback;

  /// Type of the refactoring options, or null if the refactoring has no
  /// options.
  final TypeObject? options;

  Refactoring(this.kind, this.feedback, this.options, dom.Element html,
      {bool? experimental})
      : super(html, experimental, false);
}

/// A collection of refactoring definitions.
class Refactorings extends ApiNode with IterableMixin<Refactoring> {
  final List<Refactoring> refactorings;

  Refactorings(this.refactorings, dom.Element html, {bool? experimental})
      : super(html, experimental, false);

  @override
  Iterator<Refactoring> get iterator => refactorings.iterator;
}

/// Description of a request method.
class Request extends ApiNode {
  /// Name of the domain enclosing this request.
  final String domainName;

  /// Name of the request, without the domain prefix.
  final String method;

  /// Type of the object associated with the "params" key in the request object,
  /// or null if the request has no parameters.
  final TypeObject? params;

  /// Type of the object associated with the "result" key in the response
  /// object, or null if the response has no results.
  final TypeObject? result;

  Request(
      this.domainName, this.method, this.params, this.result, dom.Element html,
      {bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);

  /// Get the name of the request, including the domain prefix.
  String get longMethod => '$domainName.$method';

  /// Get the full type of the request object, including the common "id" and
  /// "method" fields.
  TypeDecl get requestType {
    var fields = <TypeObjectField>[
      TypeObjectField('id', TypeReference('String', null), null),
      TypeObjectField('method', TypeReference('String', null), null,
          value: '$domainName.$method')
    ];
    if (params != null) {
      fields.add(TypeObjectField('params', params!, null));
    }
    return TypeObject(fields, null);
  }

  /// Get the full type of the response object, including the common "id" and
  /// "error" fields.
  TypeDecl get responseType {
    var fields = <TypeObjectField>[
      TypeObjectField('id', TypeReference('String', null), null),
      TypeObjectField('error', TypeReference('RequestError', null), null,
          optional: true)
    ];
    if (result != null) {
      fields.add(TypeObjectField('result', result!, null));
    }
    return TypeObject(fields, null);
  }
}

/// Base class for all possible types.
abstract class TypeDecl extends ApiNode {
  TypeDecl(dom.Element? html, bool? experimental, bool? deprecated)
      : super(html, experimental, deprecated);

  T accept<T>(ApiVisitor<T> visitor);
}

/// Description of a named type definition.
class TypeDefinition extends ApiNode {
  final String name;
  final TypeDecl type;

  bool isExternal = false;

  TypeDefinition(this.name, this.type, dom.Element html,
      {bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);
}

/// Type of an enum. We represent enums in JSON as strings, so this type
/// declaration simply lists the allowed values.
class TypeEnum extends TypeDecl {
  final List<TypeEnumValue> values;

  TypeEnum(this.values, dom.Element html,
      {bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);

  @override
  T accept<T>(ApiVisitor<T> visitor) => visitor.visitTypeEnum(this);
}

/// Description of a single allowed value for an enum.
class TypeEnumValue extends ApiNode {
  final String value;

  TypeEnumValue(this.value, dom.Element html,
      {bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);
}

/// Type of a JSON list.
class TypeList extends TypeDecl {
  final TypeDecl itemType;

  TypeList(this.itemType, dom.Element html, {bool? experimental})
      : super(html, experimental, false);

  @override
  T accept<T>(ApiVisitor<T> visitor) => visitor.visitTypeList(this);
}

/// Type of a JSON map.
class TypeMap extends TypeDecl {
  /// Type of map keys. Note that since JSON map keys must always be strings,
  /// this must either be a [TypeReference] for [String], or a [TypeReference]
  /// to a type which is defined in the API as an enum or a synonym for
  /// [String].
  final TypeReference keyType;

  /// Type of map values.
  final TypeDecl valueType;

  TypeMap(this.keyType, this.valueType, dom.Element html, {bool? experimental})
      : super(html, experimental, false);

  @override
  T accept<T>(ApiVisitor<T> visitor) => visitor.visitTypeMap(this);
}

/// Type of a JSON object with specified fields, some of which may be optional.
class TypeObject extends TypeDecl {
  final List<TypeObjectField> fields;

  TypeObject(this.fields, dom.Element? html,
      {bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);

  @override
  T accept<T>(ApiVisitor<T> visitor) => visitor.visitTypeObject(this);

  /// Return the field with the given [name], or null if there is no such field.
  TypeObjectField? getField(String name) {
    for (var field in fields) {
      if (field.name == name) {
        return field;
      }
    }
    return null;
  }
}

/// Description of a single field in a [TypeObject].
class TypeObjectField extends ApiNode {
  final String name;
  final TypeDecl type;
  final bool optional;

  /// Value that the field is required to contain, or null if it may vary.
  final Object? value;

  TypeObjectField(this.name, this.type, dom.Element? html,
      {this.optional = false, this.value, bool? experimental, bool? deprecated})
      : super(html, experimental, deprecated);
}

/// A reference to a type which is either defined elsewhere in the API or which
/// is built-in ([String], [bool], or [int]).
class TypeReference extends TypeDecl {
  final String typeName;

  TypeReference(this.typeName, dom.Element? html, {bool? experimental})
      : super(html, experimental, false) {
    if (typeName.isEmpty) {
      throw Exception('Empty type name');
    }
  }

  @override
  T accept<T>(ApiVisitor<T> visitor) => visitor.visitTypeReference(this);
}

/// A collection of type definitions.
class Types extends ApiNode with IterableMixin<TypeDefinition> {
  final Map<String, TypeDefinition> types;

  List<String> importUris = <String>[];

  Types(this.types, dom.Element html, {bool? experimental})
      : super(html, experimental, false);

  @override
  Iterator<TypeDefinition> get iterator => types.values.iterator;

  Iterable<String> get keys => types.keys;

  TypeDefinition? operator [](String typeName) => types[typeName];

  bool containsKey(String typeName) => types.containsKey(typeName);
}

/// Type which represents a union among multiple choices.
class TypeUnion extends TypeDecl {
  final List<TypeDecl> choices;

  /// The field that is used to disambiguate this union
  final String field;

  TypeUnion(this.choices, this.field, dom.Element html, {bool? experimental})
      : super(html, experimental, false);

  @override
  T accept<T>(ApiVisitor<T> visitor) => visitor.visitTypeUnion(this);
}
