/*
 * 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 CreateSessionResponse extends ExtensionObjectDefinition implements Message {

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

  // Properties.
  protected final ResponseHeader responseHeader;
  protected final NodeId sessionId;
  protected final NodeId authenticationToken;
  protected final double revisedSessionTimeout;
  protected final PascalByteString serverNonce;
  protected final PascalByteString serverCertificate;
  protected final List<EndpointDescription> serverEndpoints;
  protected final List<SignedSoftwareCertificate> serverSoftwareCertificates;
  protected final SignatureData serverSignature;
  protected final long maxRequestMessageSize;

  public CreateSessionResponse(
      ResponseHeader responseHeader,
      NodeId sessionId,
      NodeId authenticationToken,
      double revisedSessionTimeout,
      PascalByteString serverNonce,
      PascalByteString serverCertificate,
      List<EndpointDescription> serverEndpoints,
      List<SignedSoftwareCertificate> serverSoftwareCertificates,
      SignatureData serverSignature,
      long maxRequestMessageSize) {
    super();
    this.responseHeader = responseHeader;
    this.sessionId = sessionId;
    this.authenticationToken = authenticationToken;
    this.revisedSessionTimeout = revisedSessionTimeout;
    this.serverNonce = serverNonce;
    this.serverCertificate = serverCertificate;
    this.serverEndpoints = serverEndpoints;
    this.serverSoftwareCertificates = serverSoftwareCertificates;
    this.serverSignature = serverSignature;
    this.maxRequestMessageSize = maxRequestMessageSize;
  }

  public ResponseHeader getResponseHeader() {
    return responseHeader;
  }

  public NodeId getSessionId() {
    return sessionId;
  }

  public NodeId getAuthenticationToken() {
    return authenticationToken;
  }

  public double getRevisedSessionTimeout() {
    return revisedSessionTimeout;
  }

  public PascalByteString getServerNonce() {
    return serverNonce;
  }

  public PascalByteString getServerCertificate() {
    return serverCertificate;
  }

  public List<EndpointDescription> getServerEndpoints() {
    return serverEndpoints;
  }

  public List<SignedSoftwareCertificate> getServerSoftwareCertificates() {
    return serverSoftwareCertificates;
  }

  public SignatureData getServerSignature() {
    return serverSignature;
  }

  public long getMaxRequestMessageSize() {
    return maxRequestMessageSize;
  }

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

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

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

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

    // Simple Field (revisedSessionTimeout)
    writeSimpleField("revisedSessionTimeout", revisedSessionTimeout, writeDouble(writeBuffer, 64));

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

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

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

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

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

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

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

    // Simple Field (maxRequestMessageSize)
    writeSimpleField(
        "maxRequestMessageSize", maxRequestMessageSize, writeUnsignedLong(writeBuffer, 32));

    writeBuffer.popContext("CreateSessionResponse");
  }

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

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

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

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

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

    // Simple field (revisedSessionTimeout)
    lengthInBits += 64;

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

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

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

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

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

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

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

    // Simple field (maxRequestMessageSize)
    lengthInBits += 32;

    return lengthInBits;
  }

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

    ResponseHeader responseHeader =
        readSimpleField(
            "responseHeader",
            readComplex(
                () ->
                    (ResponseHeader) ExtensionObjectDefinition.staticParse(readBuffer, (int) (394)),
                readBuffer));

    NodeId sessionId =
        readSimpleField("sessionId", readComplex(() -> NodeId.staticParse(readBuffer), readBuffer));

    NodeId authenticationToken =
        readSimpleField(
            "authenticationToken", readComplex(() -> NodeId.staticParse(readBuffer), readBuffer));

    double revisedSessionTimeout =
        readSimpleField("revisedSessionTimeout", readDouble(readBuffer, 64));

    PascalByteString serverNonce =
        readSimpleField(
            "serverNonce", readComplex(() -> PascalByteString.staticParse(readBuffer), readBuffer));

    PascalByteString serverCertificate =
        readSimpleField(
            "serverCertificate",
            readComplex(() -> PascalByteString.staticParse(readBuffer), readBuffer));

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

    List<EndpointDescription> serverEndpoints =
        readCountArrayField(
            "serverEndpoints",
            readComplex(
                () ->
                    (EndpointDescription)
                        ExtensionObjectDefinition.staticParse(readBuffer, (int) (314)),
                readBuffer),
            noOfServerEndpoints);

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

    List<SignedSoftwareCertificate> serverSoftwareCertificates =
        readCountArrayField(
            "serverSoftwareCertificates",
            readComplex(
                () ->
                    (SignedSoftwareCertificate)
                        ExtensionObjectDefinition.staticParse(readBuffer, (int) (346)),
                readBuffer),
            noOfServerSoftwareCertificates);

    SignatureData serverSignature =
        readSimpleField(
            "serverSignature",
            readComplex(
                () ->
                    (SignatureData) ExtensionObjectDefinition.staticParse(readBuffer, (int) (458)),
                readBuffer));

    long maxRequestMessageSize =
        readSimpleField("maxRequestMessageSize", readUnsignedLong(readBuffer, 32));

    readBuffer.closeContext("CreateSessionResponse");
    // Create the instance
    return new CreateSessionResponseBuilderImpl(
        responseHeader,
        sessionId,
        authenticationToken,
        revisedSessionTimeout,
        serverNonce,
        serverCertificate,
        serverEndpoints,
        serverSoftwareCertificates,
        serverSignature,
        maxRequestMessageSize);
  }

  public static class CreateSessionResponseBuilderImpl
      implements ExtensionObjectDefinition.ExtensionObjectDefinitionBuilder {
    private final ResponseHeader responseHeader;
    private final NodeId sessionId;
    private final NodeId authenticationToken;
    private final double revisedSessionTimeout;
    private final PascalByteString serverNonce;
    private final PascalByteString serverCertificate;
    private final List<EndpointDescription> serverEndpoints;
    private final List<SignedSoftwareCertificate> serverSoftwareCertificates;
    private final SignatureData serverSignature;
    private final long maxRequestMessageSize;

    public CreateSessionResponseBuilderImpl(
        ResponseHeader responseHeader,
        NodeId sessionId,
        NodeId authenticationToken,
        double revisedSessionTimeout,
        PascalByteString serverNonce,
        PascalByteString serverCertificate,
        List<EndpointDescription> serverEndpoints,
        List<SignedSoftwareCertificate> serverSoftwareCertificates,
        SignatureData serverSignature,
        long maxRequestMessageSize) {
      this.responseHeader = responseHeader;
      this.sessionId = sessionId;
      this.authenticationToken = authenticationToken;
      this.revisedSessionTimeout = revisedSessionTimeout;
      this.serverNonce = serverNonce;
      this.serverCertificate = serverCertificate;
      this.serverEndpoints = serverEndpoints;
      this.serverSoftwareCertificates = serverSoftwareCertificates;
      this.serverSignature = serverSignature;
      this.maxRequestMessageSize = maxRequestMessageSize;
    }

    public CreateSessionResponse build() {
      CreateSessionResponse createSessionResponse =
          new CreateSessionResponse(
              responseHeader,
              sessionId,
              authenticationToken,
              revisedSessionTimeout,
              serverNonce,
              serverCertificate,
              serverEndpoints,
              serverSoftwareCertificates,
              serverSignature,
              maxRequestMessageSize);
      return createSessionResponse;
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof CreateSessionResponse)) {
      return false;
    }
    CreateSessionResponse that = (CreateSessionResponse) o;
    return (getResponseHeader() == that.getResponseHeader())
        && (getSessionId() == that.getSessionId())
        && (getAuthenticationToken() == that.getAuthenticationToken())
        && (getRevisedSessionTimeout() == that.getRevisedSessionTimeout())
        && (getServerNonce() == that.getServerNonce())
        && (getServerCertificate() == that.getServerCertificate())
        && (getServerEndpoints() == that.getServerEndpoints())
        && (getServerSoftwareCertificates() == that.getServerSoftwareCertificates())
        && (getServerSignature() == that.getServerSignature())
        && (getMaxRequestMessageSize() == that.getMaxRequestMessageSize())
        && super.equals(that)
        && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        super.hashCode(),
        getResponseHeader(),
        getSessionId(),
        getAuthenticationToken(),
        getRevisedSessionTimeout(),
        getServerNonce(),
        getServerCertificate(),
        getServerEndpoints(),
        getServerSoftwareCertificates(),
        getServerSignature(),
        getMaxRequestMessageSize());
  }

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