// 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 as TypeReference).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);
}
