/*
 * 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.eip.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 ServicesResponse extends TypeId implements Message {

  // Accessors for discriminator values.
  public Integer getId() {
    return (int) 0x0100;
  }

  // Properties.
  protected final int encapsulationProtocol;
  protected final boolean supportsCIPEncapsulation;
  protected final boolean supportsUDP;
  protected final byte[] data;

  public ServicesResponse(
      int encapsulationProtocol,
      boolean supportsCIPEncapsulation,
      boolean supportsUDP,
      byte[] data) {
    super();
    this.encapsulationProtocol = encapsulationProtocol;
    this.supportsCIPEncapsulation = supportsCIPEncapsulation;
    this.supportsUDP = supportsUDP;
    this.data = data;
  }

  public int getEncapsulationProtocol() {
    return encapsulationProtocol;
  }

  public boolean getSupportsCIPEncapsulation() {
    return supportsCIPEncapsulation;
  }

  public boolean getSupportsUDP() {
    return supportsUDP;
  }

  public byte[] getData() {
    return data;
  }

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

    // Implicit Field (serviceLen) (Used for parsing, but its value is not stored as it's implicitly
    // given by the objects content)
    int serviceLen = (int) ((getLengthInBytes()) - (4));
    writeImplicitField("serviceLen", serviceLen, writeUnsignedInt(writeBuffer, 16));

    // Simple Field (encapsulationProtocol)
    writeSimpleField(
        "encapsulationProtocol", encapsulationProtocol, writeUnsignedInt(writeBuffer, 16));

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

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

    // Reserved Field (reserved)
    writeReservedField("reserved", (short) 0x00, writeUnsignedShort(writeBuffer, 12));

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

    // Array Field (data)
    writeByteArrayField("data", data, writeByteArray(writeBuffer, 8));

    writeBuffer.popContext("ServicesResponse");
  }

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

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

    // Implicit Field (serviceLen)
    lengthInBits += 16;

    // Simple field (encapsulationProtocol)
    lengthInBits += 16;

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

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

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

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

    // Array field
    if (data != null) {
      lengthInBits += 8 * data.length;
    }

    return lengthInBits;
  }

  public static TypeIdBuilder staticParseTypeIdBuilder(ReadBuffer readBuffer)
      throws ParseException {
    readBuffer.pullContext("ServicesResponse");
    PositionAware positionAware = readBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    int serviceLen = readImplicitField("serviceLen", readUnsignedInt(readBuffer, 16));

    int encapsulationProtocol =
        readSimpleField("encapsulationProtocol", readUnsignedInt(readBuffer, 16));

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

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

    Short reservedField1 =
        readReservedField("reserved", readUnsignedShort(readBuffer, 12), (short) 0x00);

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

    byte[] data = readBuffer.readByteArray("data", Math.toIntExact((serviceLen) - (4)));

    readBuffer.closeContext("ServicesResponse");
    // Create the instance
    return new ServicesResponseBuilderImpl(
        encapsulationProtocol, supportsCIPEncapsulation, supportsUDP, data);
  }

  public static class ServicesResponseBuilderImpl implements TypeId.TypeIdBuilder {
    private final int encapsulationProtocol;
    private final boolean supportsCIPEncapsulation;
    private final boolean supportsUDP;
    private final byte[] data;

    public ServicesResponseBuilderImpl(
        int encapsulationProtocol,
        boolean supportsCIPEncapsulation,
        boolean supportsUDP,
        byte[] data) {
      this.encapsulationProtocol = encapsulationProtocol;
      this.supportsCIPEncapsulation = supportsCIPEncapsulation;
      this.supportsUDP = supportsUDP;
      this.data = data;
    }

    public ServicesResponse build() {
      ServicesResponse servicesResponse =
          new ServicesResponse(encapsulationProtocol, supportsCIPEncapsulation, supportsUDP, data);
      return servicesResponse;
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof ServicesResponse)) {
      return false;
    }
    ServicesResponse that = (ServicesResponse) o;
    return (getEncapsulationProtocol() == that.getEncapsulationProtocol())
        && (getSupportsCIPEncapsulation() == that.getSupportsCIPEncapsulation())
        && (getSupportsUDP() == that.getSupportsUDP())
        && (getData() == that.getData())
        && super.equals(that)
        && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        super.hashCode(),
        getEncapsulationProtocol(),
        getSupportsCIPEncapsulation(),
        getSupportsUDP(),
        getData());
  }

  @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";
  }
}
