/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.plc4x.java.opcua.readwrite;

import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
import static org.apache.plc4x.java.spi.generation.StaticHelper.*;

import java.time.*;
import java.util.*;
import org.apache.plc4x.java.api.exceptions.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.spi.codegen.*;
import org.apache.plc4x.java.spi.codegen.fields.*;
import org.apache.plc4x.java.spi.codegen.io.*;
import org.apache.plc4x.java.spi.generation.*;

// Code generated by code-generation. DO NOT EDIT.

public class PubSubConnectionDataType extends ExtensionObjectDefinition implements Message {

  // Accessors for discriminator values.
  public Integer getExtensionId() {
    return (int) 15619;
  }

  // Properties.
  protected final PascalString name;
  protected final boolean enabled;
  protected final Variant publisherId;
  protected final PascalString transportProfileUri;
  protected final ExtensionObject address;
  protected final List<KeyValuePair> connectionProperties;
  protected final ExtensionObject transportSettings;
  protected final List<WriterGroupDataType> writerGroups;
  protected final List<ReaderGroupDataType> readerGroups;

  public PubSubConnectionDataType(
      PascalString name,
      boolean enabled,
      Variant publisherId,
      PascalString transportProfileUri,
      ExtensionObject address,
      List<KeyValuePair> connectionProperties,
      ExtensionObject transportSettings,
      List<WriterGroupDataType> writerGroups,
      List<ReaderGroupDataType> readerGroups) {
    super();
    this.name = name;
    this.enabled = enabled;
    this.publisherId = publisherId;
    this.transportProfileUri = transportProfileUri;
    this.address = address;
    this.connectionProperties = connectionProperties;
    this.transportSettings = transportSettings;
    this.writerGroups = writerGroups;
    this.readerGroups = readerGroups;
  }

  public PascalString getName() {
    return name;
  }

  public boolean getEnabled() {
    return enabled;
  }

  public Variant getPublisherId() {
    return publisherId;
  }

  public PascalString getTransportProfileUri() {
    return transportProfileUri;
  }

  public ExtensionObject getAddress() {
    return address;
  }

  public List<KeyValuePair> getConnectionProperties() {
    return connectionProperties;
  }

  public ExtensionObject getTransportSettings() {
    return transportSettings;
  }

  public List<WriterGroupDataType> getWriterGroups() {
    return writerGroups;
  }

  public List<ReaderGroupDataType> getReaderGroups() {
    return readerGroups;
  }

  @Override
  protected void serializeExtensionObjectDefinitionChild(WriteBuffer writeBuffer)
      throws SerializationException {
    PositionAware positionAware = writeBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
    writeBuffer.pushContext("PubSubConnectionDataType");

    // Simple Field (name)
    writeSimpleField("name", name, writeComplex(writeBuffer));

    // Reserved Field (reserved)
    writeReservedField("reserved", (byte) 0x00, writeUnsignedByte(writeBuffer, 7));

    // Simple Field (enabled)
    writeSimpleField("enabled", enabled, writeBoolean(writeBuffer));

    // Simple Field (publisherId)
    writeSimpleField("publisherId", publisherId, writeComplex(writeBuffer));

    // Simple Field (transportProfileUri)
    writeSimpleField("transportProfileUri", transportProfileUri, writeComplex(writeBuffer));

    // Simple Field (address)
    writeSimpleField("address", address, writeComplex(writeBuffer));

    // Implicit Field (noOfConnectionProperties) (Used for parsing, but its value is not stored as
    // it's implicitly given by the objects content)
    int noOfConnectionProperties =
        (int) ((((getConnectionProperties()) == (null)) ? -(1) : COUNT(getConnectionProperties())));
    writeImplicitField(
        "noOfConnectionProperties", noOfConnectionProperties, writeSignedInt(writeBuffer, 32));

    // Array Field (connectionProperties)
    writeComplexTypeArrayField("connectionProperties", connectionProperties, writeBuffer);

    // Simple Field (transportSettings)
    writeSimpleField("transportSettings", transportSettings, writeComplex(writeBuffer));

    // Implicit Field (noOfWriterGroups) (Used for parsing, but its value is not stored as it's
    // implicitly given by the objects content)
    int noOfWriterGroups =
        (int) ((((getWriterGroups()) == (null)) ? -(1) : COUNT(getWriterGroups())));
    writeImplicitField("noOfWriterGroups", noOfWriterGroups, writeSignedInt(writeBuffer, 32));

    // Array Field (writerGroups)
    writeComplexTypeArrayField("writerGroups", writerGroups, writeBuffer);

    // Implicit Field (noOfReaderGroups) (Used for parsing, but its value is not stored as it's
    // implicitly given by the objects content)
    int noOfReaderGroups =
        (int) ((((getReaderGroups()) == (null)) ? -(1) : COUNT(getReaderGroups())));
    writeImplicitField("noOfReaderGroups", noOfReaderGroups, writeSignedInt(writeBuffer, 32));

    // Array Field (readerGroups)
    writeComplexTypeArrayField("readerGroups", readerGroups, writeBuffer);

    writeBuffer.popContext("PubSubConnectionDataType");
  }

  @Override
  public int getLengthInBytes() {
    return (int) Math.ceil((float) getLengthInBits() / 8.0);
  }

  @Override
  public int getLengthInBits() {
    int lengthInBits = super.getLengthInBits();
    PubSubConnectionDataType _value = this;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    // Simple field (name)
    lengthInBits += name.getLengthInBits();

    // Reserved Field (reserved)
    lengthInBits += 7;

    // Simple field (enabled)
    lengthInBits += 1;

    // Simple field (publisherId)
    lengthInBits += publisherId.getLengthInBits();

    // Simple field (transportProfileUri)
    lengthInBits += transportProfileUri.getLengthInBits();

    // Simple field (address)
    lengthInBits += address.getLengthInBits();

    // Implicit Field (noOfConnectionProperties)
    lengthInBits += 32;

    // Array field
    if (connectionProperties != null) {
      int i = 0;
      for (KeyValuePair element : connectionProperties) {
        ThreadLocalHelper.lastItemThreadLocal.set(++i >= connectionProperties.size());
        lengthInBits += element.getLengthInBits();
      }
    }

    // Simple field (transportSettings)
    lengthInBits += transportSettings.getLengthInBits();

    // Implicit Field (noOfWriterGroups)
    lengthInBits += 32;

    // Array field
    if (writerGroups != null) {
      int i = 0;
      for (WriterGroupDataType element : writerGroups) {
        ThreadLocalHelper.lastItemThreadLocal.set(++i >= writerGroups.size());
        lengthInBits += element.getLengthInBits();
      }
    }

    // Implicit Field (noOfReaderGroups)
    lengthInBits += 32;

    // Array field
    if (readerGroups != null) {
      int i = 0;
      for (ReaderGroupDataType element : readerGroups) {
        ThreadLocalHelper.lastItemThreadLocal.set(++i >= readerGroups.size());
        lengthInBits += element.getLengthInBits();
      }
    }

    return lengthInBits;
  }

  public static ExtensionObjectDefinitionBuilder staticParseExtensionObjectDefinitionBuilder(
      ReadBuffer readBuffer, Integer extensionId) throws ParseException {
    readBuffer.pullContext("PubSubConnectionDataType");
    PositionAware positionAware = readBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    PascalString name =
        readSimpleField(
            "name", readComplex(() -> PascalString.staticParse(readBuffer), readBuffer));

    Byte reservedField0 =
        readReservedField("reserved", readUnsignedByte(readBuffer, 7), (byte) 0x00);

    boolean enabled = readSimpleField("enabled", readBoolean(readBuffer));

    Variant publisherId =
        readSimpleField(
            "publisherId", readComplex(() -> Variant.staticParse(readBuffer), readBuffer));

    PascalString transportProfileUri =
        readSimpleField(
            "transportProfileUri",
            readComplex(() -> PascalString.staticParse(readBuffer), readBuffer));

    ExtensionObject address =
        readSimpleField(
            "address",
            readComplex(
                () -> ExtensionObject.staticParse(readBuffer, (boolean) (true)), readBuffer));

    int noOfConnectionProperties =
        readImplicitField("noOfConnectionProperties", readSignedInt(readBuffer, 32));

    List<KeyValuePair> connectionProperties =
        readCountArrayField(
            "connectionProperties",
            readComplex(
                () ->
                    (KeyValuePair) ExtensionObjectDefinition.staticParse(readBuffer, (int) (14535)),
                readBuffer),
            noOfConnectionProperties);

    ExtensionObject transportSettings =
        readSimpleField(
            "transportSettings",
            readComplex(
                () -> ExtensionObject.staticParse(readBuffer, (boolean) (true)), readBuffer));

    int noOfWriterGroups = readImplicitField("noOfWriterGroups", readSignedInt(readBuffer, 32));

    List<WriterGroupDataType> writerGroups =
        readCountArrayField(
            "writerGroups",
            readComplex(
                () ->
                    (WriterGroupDataType)
                        ExtensionObjectDefinition.staticParse(readBuffer, (int) (15482)),
                readBuffer),
            noOfWriterGroups);

    int noOfReaderGroups = readImplicitField("noOfReaderGroups", readSignedInt(readBuffer, 32));

    List<ReaderGroupDataType> readerGroups =
        readCountArrayField(
            "readerGroups",
            readComplex(
                () ->
                    (ReaderGroupDataType)
                        ExtensionObjectDefinition.staticParse(readBuffer, (int) (15522)),
                readBuffer),
            noOfReaderGroups);

    readBuffer.closeContext("PubSubConnectionDataType");
    // Create the instance
    return new PubSubConnectionDataTypeBuilderImpl(
        name,
        enabled,
        publisherId,
        transportProfileUri,
        address,
        connectionProperties,
        transportSettings,
        writerGroups,
        readerGroups);
  }

  public static class PubSubConnectionDataTypeBuilderImpl
      implements ExtensionObjectDefinition.ExtensionObjectDefinitionBuilder {
    private final PascalString name;
    private final boolean enabled;
    private final Variant publisherId;
    private final PascalString transportProfileUri;
    private final ExtensionObject address;
    private final List<KeyValuePair> connectionProperties;
    private final ExtensionObject transportSettings;
    private final List<WriterGroupDataType> writerGroups;
    private final List<ReaderGroupDataType> readerGroups;

    public PubSubConnectionDataTypeBuilderImpl(
        PascalString name,
        boolean enabled,
        Variant publisherId,
        PascalString transportProfileUri,
        ExtensionObject address,
        List<KeyValuePair> connectionProperties,
        ExtensionObject transportSettings,
        List<WriterGroupDataType> writerGroups,
        List<ReaderGroupDataType> readerGroups) {
      this.name = name;
      this.enabled = enabled;
      this.publisherId = publisherId;
      this.transportProfileUri = transportProfileUri;
      this.address = address;
      this.connectionProperties = connectionProperties;
      this.transportSettings = transportSettings;
      this.writerGroups = writerGroups;
      this.readerGroups = readerGroups;
    }

    public PubSubConnectionDataType build() {
      PubSubConnectionDataType pubSubConnectionDataType =
          new PubSubConnectionDataType(
              name,
              enabled,
              publisherId,
              transportProfileUri,
              address,
              connectionProperties,
              transportSettings,
              writerGroups,
              readerGroups);
      return pubSubConnectionDataType;
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof PubSubConnectionDataType)) {
      return false;
    }
    PubSubConnectionDataType that = (PubSubConnectionDataType) o;
    return (getName() == that.getName())
        && (getEnabled() == that.getEnabled())
        && (getPublisherId() == that.getPublisherId())
        && (getTransportProfileUri() == that.getTransportProfileUri())
        && (getAddress() == that.getAddress())
        && (getConnectionProperties() == that.getConnectionProperties())
        && (getTransportSettings() == that.getTransportSettings())
        && (getWriterGroups() == that.getWriterGroups())
        && (getReaderGroups() == that.getReaderGroups())
        && super.equals(that)
        && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        super.hashCode(),
        getName(),
        getEnabled(),
        getPublisherId(),
        getTransportProfileUri(),
        getAddress(),
        getConnectionProperties(),
        getTransportSettings(),
        getWriterGroups(),
        getReaderGroups());
  }

  @Override
  public String toString() {
    WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true);
    try {
      writeBufferBoxBased.writeSerializable(this);
    } catch (SerializationException e) {
      throw new RuntimeException(e);
    }
    return "\n" + writeBufferBoxBased.getBox().toString() + "\n";
  }
}
