/*
 * Copyright (c) 2019, 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.
 *
 * This file has been automatically generated. Please do not edit it manually.
 * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
 */
package org.dartlang.analysis.server.protocol;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import com.google.dart.server.utilities.general.JsonUtilities;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

/**
 * The hover information associated with a specific location.
 *
 * @coverage dart.server.generated.types
 */
@SuppressWarnings("unused")
public class HoverInformation {

  public static final List<HoverInformation> EMPTY_LIST = List.of();

  /**
   * The offset of the range of characters that encompasses the cursor position and has the same
   * hover information as the cursor position.
   */
  private final int offset;

  /**
   * The length of the range of characters that encompasses the cursor position and has the same
   * hover information as the cursor position.
   */
  private final int length;

  /**
   * The path to the defining compilation unit of the library in which the referenced element is
   * declared. This data is omitted if there is no referenced element, or if the element is declared
   * inside an HTML file.
   */
  private final String containingLibraryPath;

  /**
   * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
   * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
   * HTML file.
   */
  private final String containingLibraryName;

  /**
   * A human-readable description of the class declaring the element being referenced. This data is
   * omitted if there is no referenced element, or if the element is not a class member.
   */
  private final String containingClassDescription;

  /**
   * The dartdoc associated with the referenced element. Other than the removal of the comment
   * delimiters, including leading asterisks in the case of a block comment, the dartdoc is
   * unprocessed markdown. This data is omitted if there is no referenced element, or if the element
   * has no dartdoc.
   */
  private final String dartdoc;

  /**
   * A human-readable description of the element being referenced. This data is omitted if there is
   * no referenced element.
   */
  private final String elementDescription;

  /**
   * A human-readable description of the kind of element being referenced (such as "class" or
   * "function type alias"). This data is omitted if there is no referenced element.
   */
  private final String elementKind;

  /**
   * True if the referenced element is deprecated.
   */
  private final Boolean isDeprecated;

  /**
   * A human-readable description of the parameter corresponding to the expression being hovered
   * over. This data is omitted if the location is not in an argument to a function.
   */
  private final String parameter;

  /**
   * The name of the propagated type of the expression. This data is omitted if the location does not
   * correspond to an expression or if there is no propagated type information.
   */
  private final String propagatedType;

  /**
   * The name of the static type of the expression. This data is omitted if the location does not
   * correspond to an expression.
   */
  private final String staticType;

  /**
   * Constructor for {@link HoverInformation}.
   */
  public HoverInformation(int offset, int length, String containingLibraryPath, String containingLibraryName, String containingClassDescription, String dartdoc, String elementDescription, String elementKind, Boolean isDeprecated, String parameter, String propagatedType, String staticType) {
    this.offset = offset;
    this.length = length;
    this.containingLibraryPath = containingLibraryPath;
    this.containingLibraryName = containingLibraryName;
    this.containingClassDescription = containingClassDescription;
    this.dartdoc = dartdoc;
    this.elementDescription = elementDescription;
    this.elementKind = elementKind;
    this.isDeprecated = isDeprecated;
    this.parameter = parameter;
    this.propagatedType = propagatedType;
    this.staticType = staticType;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof HoverInformation other) {
      return
        other.offset == offset &&
        other.length == length &&
        Objects.equals(other.containingLibraryPath, containingLibraryPath) &&
        Objects.equals(other.containingLibraryName, containingLibraryName) &&
        Objects.equals(other.containingClassDescription, containingClassDescription) &&
        Objects.equals(other.dartdoc, dartdoc) &&
        Objects.equals(other.elementDescription, elementDescription) &&
        Objects.equals(other.elementKind, elementKind) &&
        Objects.equals(other.isDeprecated, isDeprecated) &&
        Objects.equals(other.parameter, parameter) &&
        Objects.equals(other.propagatedType, propagatedType) &&
        Objects.equals(other.staticType, staticType);
    }
    return false;
  }

  public static HoverInformation fromJson(JsonObject jsonObject) {
    int offset = jsonObject.get("offset").getAsInt();
    int length = jsonObject.get("length").getAsInt();
    String containingLibraryPath = jsonObject.get("containingLibraryPath") == null ? null : jsonObject.get("containingLibraryPath").getAsString();
    String containingLibraryName = jsonObject.get("containingLibraryName") == null ? null : jsonObject.get("containingLibraryName").getAsString();
    String containingClassDescription = jsonObject.get("containingClassDescription") == null ? null : jsonObject.get("containingClassDescription").getAsString();
    String dartdoc = jsonObject.get("dartdoc") == null ? null : jsonObject.get("dartdoc").getAsString();
    String elementDescription = jsonObject.get("elementDescription") == null ? null : jsonObject.get("elementDescription").getAsString();
    String elementKind = jsonObject.get("elementKind") == null ? null : jsonObject.get("elementKind").getAsString();
    Boolean isDeprecated = jsonObject.get("isDeprecated") == null ? null : jsonObject.get("isDeprecated").getAsBoolean();
    String parameter = jsonObject.get("parameter") == null ? null : jsonObject.get("parameter").getAsString();
    String propagatedType = jsonObject.get("propagatedType") == null ? null : jsonObject.get("propagatedType").getAsString();
    String staticType = jsonObject.get("staticType") == null ? null : jsonObject.get("staticType").getAsString();
    return new HoverInformation(offset, length, containingLibraryPath, containingLibraryName, containingClassDescription, dartdoc, elementDescription, elementKind, isDeprecated, parameter, propagatedType, staticType);
  }

  public static List<HoverInformation> fromJsonArray(JsonArray jsonArray) {
    if (jsonArray == null) {
      return EMPTY_LIST;
    }
    List<HoverInformation> list = new ArrayList<>(jsonArray.size());
    for (final JsonElement element : jsonArray) {
      list.add(fromJson(element.getAsJsonObject()));
    }
    return list;
  }

  /**
   * A human-readable description of the class declaring the element being referenced. This data is
   * omitted if there is no referenced element, or if the element is not a class member.
   */
  public String getContainingClassDescription() {
    return containingClassDescription;
  }

  /**
   * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
   * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
   * HTML file.
   */
  public String getContainingLibraryName() {
    return containingLibraryName;
  }

  /**
   * The path to the defining compilation unit of the library in which the referenced element is
   * declared. This data is omitted if there is no referenced element, or if the element is declared
   * inside an HTML file.
   */
  public String getContainingLibraryPath() {
    return containingLibraryPath;
  }

  /**
   * The dartdoc associated with the referenced element. Other than the removal of the comment
   * delimiters, including leading asterisks in the case of a block comment, the dartdoc is
   * unprocessed markdown. This data is omitted if there is no referenced element, or if the element
   * has no dartdoc.
   */
  public String getDartdoc() {
    return dartdoc;
  }

  /**
   * A human-readable description of the element being referenced. This data is omitted if there is
   * no referenced element.
   */
  public String getElementDescription() {
    return elementDescription;
  }

  /**
   * A human-readable description of the kind of element being referenced (such as "class" or
   * "function type alias"). This data is omitted if there is no referenced element.
   */
  public String getElementKind() {
    return elementKind;
  }

  /**
   * True if the referenced element is deprecated.
   */
  public Boolean getIsDeprecated() {
    return isDeprecated;
  }

  /**
   * The length of the range of characters that encompasses the cursor position and has the same
   * hover information as the cursor position.
   */
  public int getLength() {
    return length;
  }

  /**
   * The offset of the range of characters that encompasses the cursor position and has the same
   * hover information as the cursor position.
   */
  public int getOffset() {
    return offset;
  }

  /**
   * A human-readable description of the parameter corresponding to the expression being hovered
   * over. This data is omitted if the location is not in an argument to a function.
   */
  public String getParameter() {
    return parameter;
  }

  /**
   * The name of the propagated type of the expression. This data is omitted if the location does not
   * correspond to an expression or if there is no propagated type information.
   */
  public String getPropagatedType() {
    return propagatedType;
  }

  /**
   * The name of the static type of the expression. This data is omitted if the location does not
   * correspond to an expression.
   */
  public String getStaticType() {
    return staticType;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
      offset,
      length,
      containingLibraryPath,
      containingLibraryName,
      containingClassDescription,
      dartdoc,
      elementDescription,
      elementKind,
      isDeprecated,
      parameter,
      propagatedType,
      staticType
    );
  }

  public JsonObject toJson() {
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("offset", offset);
    jsonObject.addProperty("length", length);
    if (containingLibraryPath != null) {
      jsonObject.addProperty("containingLibraryPath", containingLibraryPath);
    }
    if (containingLibraryName != null) {
      jsonObject.addProperty("containingLibraryName", containingLibraryName);
    }
    if (containingClassDescription != null) {
      jsonObject.addProperty("containingClassDescription", containingClassDescription);
    }
    if (dartdoc != null) {
      jsonObject.addProperty("dartdoc", dartdoc);
    }
    if (elementDescription != null) {
      jsonObject.addProperty("elementDescription", elementDescription);
    }
    if (elementKind != null) {
      jsonObject.addProperty("elementKind", elementKind);
    }
    if (isDeprecated != null) {
      jsonObject.addProperty("isDeprecated", isDeprecated);
    }
    if (parameter != null) {
      jsonObject.addProperty("parameter", parameter);
    }
    if (propagatedType != null) {
      jsonObject.addProperty("propagatedType", propagatedType);
    }
    if (staticType != null) {
      jsonObject.addProperty("staticType", staticType);
    }
    return jsonObject;
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("[");
    builder.append("offset=");
    builder.append(offset);
    builder.append(", ");
    builder.append("length=");
    builder.append(length);
    builder.append(", ");
    builder.append("containingLibraryPath=");
    builder.append(containingLibraryPath);
    builder.append(", ");
    builder.append("containingLibraryName=");
    builder.append(containingLibraryName);
    builder.append(", ");
    builder.append("containingClassDescription=");
    builder.append(containingClassDescription);
    builder.append(", ");
    builder.append("dartdoc=");
    builder.append(dartdoc);
    builder.append(", ");
    builder.append("elementDescription=");
    builder.append(elementDescription);
    builder.append(", ");
    builder.append("elementKind=");
    builder.append(elementKind);
    builder.append(", ");
    builder.append("isDeprecated=");
    builder.append(isDeprecated);
    builder.append(", ");
    builder.append("parameter=");
    builder.append(parameter);
    builder.append(", ");
    builder.append("propagatedType=");
    builder.append(propagatedType);
    builder.append(", ");
    builder.append("staticType=");
    builder.append(staticType);
    builder.append("]");
    return builder.toString();
  }

}
