/*
 * 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.s7.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 S7PayloadUserData extends S7Payload implements Message {

  // Accessors for discriminator values.
  public Short getParameterParameterType() {
    return (short) 0x00;
  }

  public Short getMessageType() {
    return (short) 0x07;
  }

  // Properties.
  protected final List<S7PayloadUserDataItem> items;

  public S7PayloadUserData(List<S7PayloadUserDataItem> items) {
    super();
    this.items = items;
  }

  public List<S7PayloadUserDataItem> getItems() {
    return items;
  }

  @Override
  protected void serializeS7PayloadChild(WriteBuffer writeBuffer) throws SerializationException {
    PositionAware positionAware = writeBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
    int startPos = positionAware.getPos();
    writeBuffer.pushContext("S7PayloadUserData");

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

    writeBuffer.popContext("S7PayloadUserData");
  }

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

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

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

    return lengthInBits;
  }

  public static S7PayloadBuilder staticParseS7PayloadBuilder(
      ReadBuffer readBuffer, Short messageType, S7Parameter parameter) throws ParseException {
    readBuffer.pullContext("S7PayloadUserData");
    PositionAware positionAware = readBuffer;
    int startPos = positionAware.getPos();
    int curPos;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    List<S7PayloadUserDataItem> items =
        readCountArrayField(
            "items",
            new DataReaderComplexDefault<>(
                () ->
                    S7PayloadUserDataItem.staticParse(
                        readBuffer,
                        (byte)
                            (CAST(
                                    CAST(parameter, S7ParameterUserData.class).getItems().get(0),
                                    S7ParameterUserDataItemCPUFunctions.class)
                                .getCpuFunctionType()),
                        (short)
                            (CAST(
                                    CAST(parameter, S7ParameterUserData.class).getItems().get(0),
                                    S7ParameterUserDataItemCPUFunctions.class)
                                .getCpuSubfunction())),
                readBuffer),
            COUNT(CAST(parameter, S7ParameterUserData.class).getItems()));

    readBuffer.closeContext("S7PayloadUserData");
    // Create the instance
    return new S7PayloadUserDataBuilderImpl(items);
  }

  public static class S7PayloadUserDataBuilderImpl implements S7Payload.S7PayloadBuilder {
    private final List<S7PayloadUserDataItem> items;

    public S7PayloadUserDataBuilderImpl(List<S7PayloadUserDataItem> items) {
      this.items = items;
    }

    public S7PayloadUserData build() {
      S7PayloadUserData s7PayloadUserData = new S7PayloadUserData(items);
      return s7PayloadUserData;
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof S7PayloadUserData)) {
      return false;
    }
    S7PayloadUserData that = (S7PayloadUserData) o;
    return (getItems() == that.getItems()) && super.equals(that) && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(super.hashCode(), getItems());
  }

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