// 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 = false})
      : super(html, experimental: experimental, deprecated: 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, `null` if built-in.
  final dom.Element? html;

  ApiNode(this.html, {this.experimental = false, this.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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: deprecated);

  @override
  dom.Element get html => super.html!;
}

/// 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) {
      var newTypeRef = api.types[type.typeName];
      if (newTypeRef == null) {
        break;
      }
      type = newTypeRef.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) {
    var params = notification.params;
    if (params != null) {
      visitTypeDecl(params);
    }
  }

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

    var options = refactoring.options;
    if (options != null) {
      visitTypeDecl(options);
    }
  }

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

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

    var result = request.result;
    if (result != null) {
      visitTypeDecl(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 = false})
      : super(html, experimental: experimental, deprecated: 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')
    ];

    final params = this.params;
    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 = false})
      : super(html, experimental: experimental, deprecated: 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 = false})
      : super(html, experimental: experimental, deprecated: 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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: 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')
    ];

    final params = this.params;
    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)
    ];

    final result = this.result;
    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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: 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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: 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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: 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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: deprecated);

  @override
  dom.Element get html => super.html!;
}

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

  TypeList(this.itemType, dom.Element html, {bool experimental = false})
      : super(html, experimental: experimental, deprecated: 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 = false})
      : super(html, experimental: experimental, deprecated: 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 = false, bool deprecated = false})
      : super(html, experimental: experimental, deprecated: 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 = false,
      bool deprecated = false})
      : super(html, experimental: experimental, deprecated: 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 = false})
      : super(html, experimental: experimental, deprecated: 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 = false})
      : super(html, experimental: experimental, deprecated: 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 = false})
      : super(html, experimental: experimental, deprecated: false);

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