// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY

package org.wpilib.networktables;

import java.nio.ByteBuffer;

/**
 * NetworkTables Entry.
 *
 * <p>For backwards compatibility, the NetworkTableEntry close() does not release the entry.
 */
@SuppressWarnings("UnnecessaryParentheses")
public final class NetworkTableEntry implements Publisher, Subscriber {
  /**
   * Construct from native handle.
   *
   * @param inst Instance
   * @param handle Native handle
   */
  public NetworkTableEntry(NetworkTableInstance inst, int handle) {
    this(new Topic(inst, NetworkTablesJNI.getTopicFromHandle(handle)), handle);
  }

  /**
   * Construct from native handle.
   *
   * @param topic Topic
   * @param handle Native handle
   */
  public NetworkTableEntry(Topic topic, int handle) {
    m_topic = topic;
    m_handle = handle;
  }

  @Override
  public void close() {}

  /**
   * Determines if the native handle is valid.
   *
   * @return True if the native handle is valid, false otherwise.
   */
  @Override
  public boolean isValid() {
    return m_handle != 0;
  }

  /**
   * Gets the native handle for the entry.
   *
   * @return Native handle
   */
  @Override
  public int getHandle() {
    return m_handle;
  }

  /**
   * Gets the subscribed-to / published-to topic.
   *
   * @return Topic
   */
  @Override
  public Topic getTopic() {
    return m_topic;
  }

  /**
   * Gets the instance for the entry.
   *
   * @return Instance
   */
  public NetworkTableInstance getInstance() {
    return m_topic.getInstance();
  }

  /**
   * Determines if the entry currently exists.
   *
   * @return True if the entry exists, false otherwise.
   */
  @Override
  public boolean exists() {
    return NetworkTablesJNI.getType(m_handle) != 0;
  }

  /**
   * Gets the name of the entry (the key).
   *
   * @return the entry's name
   */
  public String getName() {
    return NetworkTablesJNI.getEntryName(m_handle);
  }

  /**
   * Gets the type of the entry.
   *
   * @return the entry's type
   */
  public NetworkTableType getType() {
    return NetworkTableType.getFromInt(NetworkTablesJNI.getType(m_handle));
  }

  /**
   * Gets the last time the entry's value was changed.
   *
   * @return Entry last change time
   */
  @Override
  public long getLastChange() {
    return NetworkTablesJNI.getEntryLastChange(m_handle);
  }

  /**
   * Gets the entry's value. Returns a value with type NetworkTableType.UNASSIGNED if the value
   * does not exist.
   *
   * @return the entry's value
   */
  public NetworkTableValue getValue() {
    return NetworkTablesJNI.getValue(m_handle);
  }

  /**
   * Gets the entry's value as a boolean. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public boolean getBoolean(boolean defaultValue) {
    return NetworkTablesJNI.getBoolean(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a long. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public long getInteger(long defaultValue) {
    return NetworkTablesJNI.getInteger(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a float. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public float getFloat(float defaultValue) {
    return NetworkTablesJNI.getFloat(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a double. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public double getDouble(double defaultValue) {
    return NetworkTablesJNI.getDouble(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a String. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public String getString(String defaultValue) {
    return NetworkTablesJNI.getString(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a byte[]. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public byte[] getRaw(byte[] defaultValue) {
    return NetworkTablesJNI.getRaw(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a boolean[]. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public boolean[] getBooleanArray(boolean[] defaultValue) {
    return NetworkTablesJNI.getBooleanArray(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a boolean array. If the entry does not exist or is of different type,
   * it will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public Boolean[] getBooleanArray(Boolean[] defaultValue) {
    return NetworkTableValue.fromNativeBooleanArray(
        getBooleanArray(NetworkTableValue.toNativeBooleanArray(defaultValue)));
  }

  /**
   * Gets the entry's value as a long[]. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public long[] getIntegerArray(long[] defaultValue) {
    return NetworkTablesJNI.getIntegerArray(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a boolean array. If the entry does not exist or is of different type,
   * it will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public Long[] getIntegerArray(Long[] defaultValue) {
    return NetworkTableValue.fromNativeIntegerArray(
        getIntegerArray(NetworkTableValue.toNativeIntegerArray(defaultValue)));
  }

  /**
   * Gets the entry's value as a float[]. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public float[] getFloatArray(float[] defaultValue) {
    return NetworkTablesJNI.getFloatArray(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a boolean array. If the entry does not exist or is of different type,
   * it will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public Float[] getFloatArray(Float[] defaultValue) {
    return NetworkTableValue.fromNativeFloatArray(
        getFloatArray(NetworkTableValue.toNativeFloatArray(defaultValue)));
  }

  /**
   * Gets the entry's value as a double[]. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public double[] getDoubleArray(double[] defaultValue) {
    return NetworkTablesJNI.getDoubleArray(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a boolean array. If the entry does not exist or is of different type,
   * it will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public Double[] getDoubleArray(Double[] defaultValue) {
    return NetworkTableValue.fromNativeDoubleArray(
        getDoubleArray(NetworkTableValue.toNativeDoubleArray(defaultValue)));
  }

  /**
   * Gets the entry's value as a String[]. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public String[] getStringArray(String[] defaultValue) {
    return NetworkTablesJNI.getStringArray(m_handle, defaultValue);
  }

  /**
   * Gets the entry's value as a double. If the entry does not exist or is of different type, it
   * will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public Number getNumber(Number defaultValue) {
    return getDouble(defaultValue.doubleValue());
  }

  /**
   * Gets the entry's value as a double array. If the entry does not exist or is of different type,
   * it will return the default value.
   *
   * @param defaultValue the value to be returned if no value is found
   * @return the entry's value or the given default value
   */
  public Number[] getNumberArray(Number[] defaultValue) {
    return NetworkTableValue.fromNativeDoubleArray(
        getDoubleArray(NetworkTableValue.toNativeDoubleArray(defaultValue)));
  }

  /**
   * Get an array of all value changes since the last call to readQueue.
   *
   * <p>The "poll storage" subscribe option can be used to set the queue
   * depth.
   *
   * @return Array of values; empty array if no new changes have been
   *     published since the previous call.
   */
  public NetworkTableValue[] readQueue() {
    return NetworkTablesJNI.readQueueValue(m_handle);
  }

  /**
   * Checks if a data value is of a type that can be placed in a NetworkTable entry.
   *
   * @param data the data to check
   * @return true if the data can be placed in an entry, false if it cannot
   */
  public static boolean isValidDataType(Object data) {
    return switch (data) {
      case Number _, Boolean _, String _ -> true;
      case byte[] _, Byte[] _ -> true;
      case boolean[] _, Boolean[] _ -> true;
      case long[] _, Long[] _ -> true;
      case float[] _, Float[] _ -> true;
      case double[] _, Double[] _, Number[] _ -> true;
      case String[] _ -> true;
      case null, default -> false;
    };
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   * @throws IllegalArgumentException if the value is not a known type
   */
  public boolean setDefaultValue(Object defaultValue) {
    return switch (defaultValue) {
      case NetworkTableValue ntValue -> {
        long time = ntValue.getTime();
        Object otherValue = ntValue.getValue();
        yield switch (ntValue.getType()) {
          case BOOLEAN -> NetworkTablesJNI.setDefaultBoolean(m_handle, time, (Boolean) otherValue);
          case INTEGER -> NetworkTablesJNI.setDefaultInteger(
              m_handle, time, ((Number) otherValue).longValue());
          case FLOAT -> NetworkTablesJNI.setDefaultFloat(
              m_handle, time, ((Number) otherValue).floatValue());
          case DOUBLE -> NetworkTablesJNI.setDefaultDouble(
              m_handle, time, ((Number) otherValue).doubleValue());
          case STRING -> NetworkTablesJNI.setDefaultString(m_handle, time, (String) otherValue);
          case RAW -> NetworkTablesJNI.setDefaultRaw(m_handle, time, (byte[]) otherValue);
          case BOOLEAN_ARRAY -> NetworkTablesJNI.setDefaultBooleanArray(
              m_handle, time, (boolean[]) otherValue);
          case INTEGER_ARRAY -> NetworkTablesJNI.setDefaultIntegerArray(
              m_handle, time, (long[]) otherValue);
          case FLOAT_ARRAY -> NetworkTablesJNI.setDefaultFloatArray(
              m_handle, time, (float[]) otherValue);
          case DOUBLE_ARRAY -> NetworkTablesJNI.setDefaultDoubleArray(
              m_handle, time, (double[]) otherValue);
          case STRING_ARRAY -> NetworkTablesJNI.setDefaultStringArray(
              m_handle, time, (String[]) otherValue);
          default -> true;
        };
      }
      case Boolean value -> setDefaultBoolean(value);
      case Integer value -> setDefaultInteger(value);
      case Float value -> setDefaultFloat(value);
      case Number value -> setDefaultNumber(value);
      case String value -> setDefaultString(value);
      case byte[] value -> setDefaultRaw(value);
      case boolean[] value -> setDefaultBooleanArray(value);
      case long[] value -> setDefaultIntegerArray(value);
      case float[] value -> setDefaultFloatArray(value);
      case double[] value -> setDefaultDoubleArray(value);
      case Boolean[] value -> setDefaultBooleanArray(value);
      case Long[] value -> setDefaultIntegerArray(value);
      case Float[] value -> setDefaultFloatArray(value);
      case Number[] value -> setDefaultNumberArray(value);
      case String[] value -> setDefaultStringArray(value);
      default -> throw new IllegalArgumentException(
          "Value of type " + defaultValue.getClass().getName() + " cannot be put into a table");
    };
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultBoolean(boolean defaultValue) {
    return NetworkTablesJNI.setDefaultBoolean(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultInteger(long defaultValue) {
    return NetworkTablesJNI.setDefaultInteger(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultFloat(float defaultValue) {
    return NetworkTablesJNI.setDefaultFloat(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultDouble(double defaultValue) {
    return NetworkTablesJNI.setDefaultDouble(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultString(String defaultValue) {
    return NetworkTablesJNI.setDefaultString(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultRaw(byte[] defaultValue) {
    return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set; will send from defaultValue.position() to
   *                     defaultValue.capacity()
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultRaw(ByteBuffer defaultValue) {
    return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @param start Start position of data (in buffer)
   * @param len Length of data (must be less than or equal to value.length - start)
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultRaw(byte[] defaultValue, int start, int len) {
    return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue, start, len);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @param start Start position of data (in buffer)
   * @param len Length of data (must be less than or equal to value.capacity() - start)
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultRaw(ByteBuffer defaultValue, int start, int len) {
    return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue, start, len);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultBooleanArray(boolean[] defaultValue) {
    return NetworkTablesJNI.setDefaultBooleanArray(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultBooleanArray(Boolean[] defaultValue) {
    return setDefaultBooleanArray(NetworkTableValue.toNativeBooleanArray(defaultValue));
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultIntegerArray(long[] defaultValue) {
    return NetworkTablesJNI.setDefaultIntegerArray(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultIntegerArray(Long[] defaultValue) {
    return setDefaultIntegerArray(NetworkTableValue.toNativeIntegerArray(defaultValue));
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultFloatArray(float[] defaultValue) {
    return NetworkTablesJNI.setDefaultFloatArray(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultFloatArray(Float[] defaultValue) {
    return setDefaultFloatArray(NetworkTableValue.toNativeFloatArray(defaultValue));
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultDoubleArray(double[] defaultValue) {
    return NetworkTablesJNI.setDefaultDoubleArray(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultDoubleArray(Double[] defaultValue) {
    return setDefaultDoubleArray(NetworkTableValue.toNativeDoubleArray(defaultValue));
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultStringArray(String[] defaultValue) {
    return NetworkTablesJNI.setDefaultStringArray(m_handle, 0, defaultValue);
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultNumber(Number defaultValue) {
    return setDefaultDouble(defaultValue.doubleValue());
  }

  /**
   * Sets the entry's value if it does not exist.
   *
   * @param defaultValue the default value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDefaultNumberArray(Number[] defaultValue) {
    return setDefaultDoubleArray(NetworkTableValue.toNativeDoubleArray(defaultValue));
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value that will be assigned
   * @return False if the table key already exists with a different type
   * @throws IllegalArgumentException if the value is not a known type
   */
  public boolean setValue(Object value) {
    return switch (value) {
      case NetworkTableValue ntValue -> {
        long time = ntValue.getTime();
        Object otherValue = ntValue.getValue();
        yield switch (ntValue.getType()) {
          case BOOLEAN -> NetworkTablesJNI.setBoolean(m_handle, time, (Boolean) otherValue);
          case INTEGER -> NetworkTablesJNI.setInteger(
              m_handle, time, ((Number) otherValue).longValue());
          case FLOAT -> NetworkTablesJNI.setFloat(
              m_handle, time, ((Number) otherValue).floatValue());
          case DOUBLE -> NetworkTablesJNI.setDouble(
              m_handle, time, ((Number) otherValue).doubleValue());
          case STRING -> NetworkTablesJNI.setString(m_handle, time, (String) otherValue);
          case RAW -> NetworkTablesJNI.setRaw(m_handle, time, (byte[]) otherValue);
          case BOOLEAN_ARRAY -> NetworkTablesJNI.setBooleanArray(
              m_handle, time, (boolean[]) otherValue);
          case INTEGER_ARRAY -> NetworkTablesJNI.setIntegerArray(
              m_handle, time, (long[]) otherValue);
          case FLOAT_ARRAY -> NetworkTablesJNI.setFloatArray(
              m_handle, time, (float[]) otherValue);
          case DOUBLE_ARRAY -> NetworkTablesJNI.setDoubleArray(
              m_handle, time, (double[]) otherValue);
          case STRING_ARRAY -> NetworkTablesJNI.setStringArray(
              m_handle, time, (String[]) otherValue);
          default -> true;
        };
      }
      case Boolean v -> setBoolean(v);
      case Long v -> setInteger(v);
      case Float v -> setFloat(v);
      case Number v -> setNumber(v);
      case String v -> setString(v);
      case byte[] v -> setRaw(v);
      case boolean[] v -> setBooleanArray(v);
      case long[] v -> setIntegerArray(v);
      case float[] v -> setFloatArray(v);
      case double[] v -> setDoubleArray(v);
      case Boolean[] v -> setBooleanArray(v);
      case Long[] v -> setIntegerArray(v);
      case Float[] v -> setFloatArray(v);
      case Number[] v -> setNumberArray(v);
      case String[] v -> setStringArray(v);
      default -> throw new IllegalArgumentException(
          "Value of type " + value.getClass().getName() + " cannot be put into a table");
    };
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setBoolean(boolean value) {
    return NetworkTablesJNI.setBoolean(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setInteger(long value) {
    return NetworkTablesJNI.setInteger(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setFloat(float value) {
    return NetworkTablesJNI.setFloat(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDouble(double value) {
    return NetworkTablesJNI.setDouble(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setString(String value) {
    return NetworkTablesJNI.setString(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setRaw(byte[] value) {
    return NetworkTablesJNI.setRaw(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set; will send from value.position() to value.capacity()
   * @return False if the entry exists with a different type
   */
  public boolean setRaw(ByteBuffer value) {
    return NetworkTablesJNI.setRaw(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @param start Start position of data (in buffer)
   * @param len Length of data (must be less than or equal to value.length - start)
   * @return False if the entry exists with a different type
   */
  public boolean setRaw(byte[] value, int start, int len) {
    return NetworkTablesJNI.setRaw(m_handle, 0, value, start, len);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @param start Start position of data (in buffer)
   * @param len Length of data (must be less than or equal to value.capacity() - start)
   * @return False if the entry exists with a different type
   */
  public boolean setRaw(ByteBuffer value, int start, int len) {
    return NetworkTablesJNI.setRaw(m_handle, 0, value, start, len);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setBooleanArray(boolean[] value) {
    return NetworkTablesJNI.setBooleanArray(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setBooleanArray(Boolean[] value) {
    return setBooleanArray(NetworkTableValue.toNativeBooleanArray(value));
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setIntegerArray(long[] value) {
    return NetworkTablesJNI.setIntegerArray(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setIntegerArray(Long[] value) {
    return setIntegerArray(NetworkTableValue.toNativeIntegerArray(value));
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setFloatArray(float[] value) {
    return NetworkTablesJNI.setFloatArray(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setFloatArray(Float[] value) {
    return setFloatArray(NetworkTableValue.toNativeFloatArray(value));
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDoubleArray(double[] value) {
    return NetworkTablesJNI.setDoubleArray(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setDoubleArray(Double[] value) {
    return setDoubleArray(NetworkTableValue.toNativeDoubleArray(value));
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setStringArray(String[] value) {
    return NetworkTablesJNI.setStringArray(m_handle, 0, value);
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setNumber(Number value) {
    return setDouble(value.doubleValue());
  }

  /**
   * Sets the entry's value.
   *
   * @param value the value to set
   * @return False if the entry exists with a different type
   */
  public boolean setNumberArray(Number[] value) {
    return setDoubleArray(NetworkTableValue.toNativeDoubleArray(value));
  }

  /** Make value persistent through program restarts. */
  public void setPersistent() {
    NetworkTablesJNI.setTopicPersistent(m_topic.getHandle(), true);
  }

  /** Stop making value persistent through program restarts. */
  public void clearPersistent() {
    NetworkTablesJNI.setTopicPersistent(m_topic.getHandle(), false);
  }

  /**
   * Returns whether the value is persistent through program restarts.
   *
   * @return True if the value is persistent.
   */
  public boolean isPersistent() {
    return NetworkTablesJNI.getTopicPersistent(m_topic.getHandle());
  }

  /** Stops publishing the entry if it's been published. */
  public void unpublish() {
    NetworkTablesJNI.unpublish(m_handle);
  }

  @Override
  public boolean equals(Object other) {
    return other == this || other instanceof NetworkTableEntry entry && m_handle == entry.m_handle;
  }

  @Override
  public int hashCode() {
    return m_handle;
  }

  private final Topic m_topic;
  private final int m_handle;
}
