/*++

Copyright (C) 2024 3MF Consortium (Original Author)

All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This file has been generated by the Automatic Component Toolkit (ACT) version 1.8.1-develop.

Abstract: This is an autogenerated Java file in order to allow an easy
 use of the 3MF Library

Interface version: 2.5.0

*/

package lib3mf;

import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.lang.ref.Cleaner;


import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

public class Object extends Resource {

	public Object(Lib3MFWrapper wrapper, Pointer handle) {
		super(wrapper, handle);
	}

	/**
	 * Retrieves an object's type
	 *
	 * @return returns object type enum.
	 * @throws Lib3MFException
	 */
	public Lib3MFWrapper.ObjectType getType() throws Lib3MFException {
		Pointer bufferObjectType = new Memory(4);
		mWrapper.checkError(this, mWrapper.lib3mf_object_gettype.invokeInt(new java.lang.Object[]{mHandle, bufferObjectType}));
		return Lib3MFWrapper.EnumConversion.convertConstToObjectType(bufferObjectType.getInt(0));
	}

	/**
	 * Sets an object's type
	 *
	 * @param objectType object type enum.
	 * @throws Lib3MFException
	 */
	public void setType(Lib3MFWrapper.ObjectType objectType) throws Lib3MFException {
		mWrapper.checkError(this, mWrapper.lib3mf_object_settype.invokeInt(new java.lang.Object[]{mHandle, Lib3MFWrapper.EnumConversion.convertObjectTypeToConst(objectType)}));
	}

	/**
	 * Retrieves an object's name
	 *
	 * @return returns object name.
	 * @throws Lib3MFException
	 */
	public String getName() throws Lib3MFException {
		Pointer bytesNeededName = new Memory(4);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getname.invokeInt(new java.lang.Object[]{mHandle, 0, bytesNeededName, null}));
		int sizeName = bytesNeededName.getInt(0);
		Pointer bufferName = new Memory(sizeName);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getname.invokeInt(new java.lang.Object[]{mHandle, sizeName, bytesNeededName, bufferName}));
		return new String(bufferName.getByteArray(0, sizeName - 1), StandardCharsets.UTF_8);
	}

	/**
	 * Sets an object's name string
	 *
	 * @param name new object name.
	 * @throws Lib3MFException
	 */
	public void setName(String name) throws Lib3MFException {
		byte[] bytesName = name.getBytes(StandardCharsets.UTF_8);
		Memory bufferName = new Memory(bytesName.length + 1);
		bufferName.write(0, bytesName, 0, bytesName.length);
		bufferName.setByte(bytesName.length, (byte)0);
		mWrapper.checkError(this, mWrapper.lib3mf_object_setname.invokeInt(new java.lang.Object[]{mHandle, bufferName}));
	}

	/**
	 * Retrieves an object's part number
	 *
	 * @return returns object part number.
	 * @throws Lib3MFException
	 */
	public String getPartNumber() throws Lib3MFException {
		Pointer bytesNeededPartNumber = new Memory(4);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getpartnumber.invokeInt(new java.lang.Object[]{mHandle, 0, bytesNeededPartNumber, null}));
		int sizePartNumber = bytesNeededPartNumber.getInt(0);
		Pointer bufferPartNumber = new Memory(sizePartNumber);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getpartnumber.invokeInt(new java.lang.Object[]{mHandle, sizePartNumber, bytesNeededPartNumber, bufferPartNumber}));
		return new String(bufferPartNumber.getByteArray(0, sizePartNumber - 1), StandardCharsets.UTF_8);
	}

	/**
	 * Sets an objects partnumber string
	 *
	 * @param partNumber new object part number.
	 * @throws Lib3MFException
	 */
	public void setPartNumber(String partNumber) throws Lib3MFException {
		byte[] bytesPartNumber = partNumber.getBytes(StandardCharsets.UTF_8);
		Memory bufferPartNumber = new Memory(bytesPartNumber.length + 1);
		bufferPartNumber.write(0, bytesPartNumber, 0, bytesPartNumber.length);
		bufferPartNumber.setByte(bytesPartNumber.length, (byte)0);
		mWrapper.checkError(this, mWrapper.lib3mf_object_setpartnumber.invokeInt(new java.lang.Object[]{mHandle, bufferPartNumber}));
	}

	/**
	 * Retrieves, if an object is a mesh object
	 *
	 * @return returns, whether the object is a mesh object
	 * @throws Lib3MFException
	 */
	public boolean isMeshObject() throws Lib3MFException {
		Pointer bufferIsMeshObject = new Memory(1);
		mWrapper.checkError(this, mWrapper.lib3mf_object_ismeshobject.invokeInt(new java.lang.Object[]{mHandle, bufferIsMeshObject}));
		return bufferIsMeshObject.getByte(0) != 0;
	}

	/**
	 * Retrieves, if an object is a components object
	 *
	 * @return returns, whether the object is a components object
	 * @throws Lib3MFException
	 */
	public boolean isComponentsObject() throws Lib3MFException {
		Pointer bufferIsComponentsObject = new Memory(1);
		mWrapper.checkError(this, mWrapper.lib3mf_object_iscomponentsobject.invokeInt(new java.lang.Object[]{mHandle, bufferIsComponentsObject}));
		return bufferIsComponentsObject.getByte(0) != 0;
	}

	/**
	 * Retrieves, if an object is a level set object
	 *
	 * @return returns, whether the object is a level set object
	 * @throws Lib3MFException
	 */
	public boolean isLevelSetObject() throws Lib3MFException {
		Pointer bufferIsLevelSetObject = new Memory(1);
		mWrapper.checkError(this, mWrapper.lib3mf_object_islevelsetobject.invokeInt(new java.lang.Object[]{mHandle, bufferIsLevelSetObject}));
		return bufferIsLevelSetObject.getByte(0) != 0;
	}

	/**
	 * Retrieves, if the object is valid according to the core spec. For mesh objects, we distinguish between the type attribute of the object:In case of object type other, this always means false.In case of object type model or solidsupport, this means, if the mesh suffices all requirements of the core spec chapter 4.1.In case of object type support or surface, this always means true.A component objects is valid if and only if it contains at least one component and all child components are valid objects.
	 *
	 * @return returns whether the object is a valid object description
	 * @throws Lib3MFException
	 */
	public boolean isValid() throws Lib3MFException {
		Pointer bufferIsValid = new Memory(1);
		mWrapper.checkError(this, mWrapper.lib3mf_object_isvalid.invokeInt(new java.lang.Object[]{mHandle, bufferIsValid}));
		return bufferIsValid.getByte(0) != 0;
	}

	/**
	 * Use an existing attachment as thumbnail for this object
	 *
	 * @param attachment Instance of a new or the existing thumbnailattachment object.
	 * @throws Lib3MFException
	 */
	public void setAttachmentAsThumbnail(Attachment attachment) throws Lib3MFException {
		Pointer attachmentHandle = null;
		if (attachment != null) {
			attachmentHandle = attachment.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "Attachment is a null value.");
		}
		mWrapper.checkError(this, mWrapper.lib3mf_object_setattachmentasthumbnail.invokeInt(new java.lang.Object[]{mHandle, attachmentHandle}));
	}

	/**
	 * Get the attachment containing the object thumbnail.
	 *
	 * @return Instance of the thumbnailattachment object or NULL.
	 * @throws Lib3MFException
	 */
	public Attachment getThumbnailAttachment() throws Lib3MFException {
		Pointer bufferAttachment = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getthumbnailattachment.invokeInt(new java.lang.Object[]{mHandle, bufferAttachment}));
		Pointer valueAttachment = bufferAttachment.getPointer(0);
		Attachment attachment = null;
		if (valueAttachment != Pointer.NULL) {
		  attachment = mWrapper.PolymorphicFactory(valueAttachment, Attachment.class);
		}
		return attachment;
	}

	/**
	 * Clears the attachment. The attachment instance is not removed from the package.
	 *
	 * @throws Lib3MFException
	 */
	public void clearThumbnailAttachment() throws Lib3MFException {
		mWrapper.checkError(this, mWrapper.lib3mf_object_clearthumbnailattachment.invokeInt(new java.lang.Object[]{mHandle}));
	}

	/**
	 * Returns the outbox of a build item
	 *
	 * @return Outbox of this build item
	 * @throws Lib3MFException
	 */
	public Box getOutbox() throws Lib3MFException {
		Pointer bufferOutbox = new Memory(Box.SIZE);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getoutbox.invokeInt(new java.lang.Object[]{mHandle, bufferOutbox}));
		Box outbox = new Box();
		outbox.readFromPointer(bufferOutbox, 0);
		return outbox;
	}

	/**
	 * Retrieves an object's uuid string (see production extension specification)
	 *
	 * @return GetUUID Result Tuple
	 * @throws Lib3MFException
	 */
	public GetUUIDResult getUUID() throws Lib3MFException {
		Pointer bufferHasUUID = new Memory(1);
		Pointer bytesNeededUUID = new Memory(4);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getuuid.invokeInt(new java.lang.Object[]{mHandle, bufferHasUUID, 0, bytesNeededUUID, null}));
		int sizeUUID = bytesNeededUUID.getInt(0);
		Pointer bufferUUID = new Memory(sizeUUID);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getuuid.invokeInt(new java.lang.Object[]{mHandle, bufferHasUUID, sizeUUID, bytesNeededUUID, bufferUUID}));
		GetUUIDResult returnTuple = new GetUUIDResult();
		returnTuple.HasUUID = bufferHasUUID.getByte(0) != 0;
		returnTuple.UUID = new String(bufferUUID.getByteArray(0, sizeUUID - 1), StandardCharsets.UTF_8);
		return returnTuple;
	}

	public static class GetUUIDResult {
		/**
		 * flag whether the build item has a UUID
		 */
		public boolean HasUUID;

		/**
		 * returns object uuid.
		 */
		public String UUID;

	}
	/**
	 * Sets a build object's uuid string (see production extension specification)
	 *
	 * @param uUID new object uuid string.
	 * @throws Lib3MFException
	 */
	public void setUUID(String uUID) throws Lib3MFException {
		byte[] bytesUUID = uUID.getBytes(StandardCharsets.UTF_8);
		Memory bufferUUID = new Memory(bytesUUID.length + 1);
		bufferUUID.write(0, bytesUUID, 0, bytesUUID.length);
		bufferUUID.setByte(bytesUUID.length, (byte)0);
		mWrapper.checkError(this, mWrapper.lib3mf_object_setuuid.invokeInt(new java.lang.Object[]{mHandle, bufferUUID}));
	}

	/**
	 * Returns the metadatagroup of this object
	 *
	 * @return returns an Instance of the metadatagroup of this object
	 * @throws Lib3MFException
	 */
	public MetaDataGroup getMetaDataGroup() throws Lib3MFException {
		Pointer bufferMetaDataGroup = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getmetadatagroup.invokeInt(new java.lang.Object[]{mHandle, bufferMetaDataGroup}));
		Pointer valueMetaDataGroup = bufferMetaDataGroup.getPointer(0);
		MetaDataGroup metaDataGroup = null;
		if (valueMetaDataGroup == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "MetaDataGroup was a null pointer");
		}
		metaDataGroup = mWrapper.PolymorphicFactory(valueMetaDataGroup, MetaDataGroup.class);
		return metaDataGroup;
	}

	/**
	 * set the meshresolution of the mesh object
	 *
	 * @param meshResolution meshresolution of this object
	 * @throws Lib3MFException
	 */
	public void setSlicesMeshResolution(Lib3MFWrapper.SlicesMeshResolution meshResolution) throws Lib3MFException {
		mWrapper.checkError(this, mWrapper.lib3mf_object_setslicesmeshresolution.invokeInt(new java.lang.Object[]{mHandle, Lib3MFWrapper.EnumConversion.convertSlicesMeshResolutionToConst(meshResolution)}));
	}

	/**
	 * get the meshresolution of the mesh object
	 *
	 * @return meshresolution of this object
	 * @throws Lib3MFException
	 */
	public Lib3MFWrapper.SlicesMeshResolution getSlicesMeshResolution() throws Lib3MFException {
		Pointer bufferMeshResolution = new Memory(4);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getslicesmeshresolution.invokeInt(new java.lang.Object[]{mHandle, bufferMeshResolution}));
		return Lib3MFWrapper.EnumConversion.convertConstToSlicesMeshResolution(bufferMeshResolution.getInt(0));
	}

	/**
	 * returns whether the Object has a slice stack. If Recursive is true, also checks whether any references object has a slice stack
	 *
	 * @param recursive check also all referenced objects?
	 * @return does the object have a slice stack?
	 * @throws Lib3MFException
	 */
	public boolean hasSlices(boolean recursive) throws Lib3MFException {
		Pointer bufferHasSlices = new Memory(1);
		mWrapper.checkError(this, mWrapper.lib3mf_object_hasslices.invokeInt(new java.lang.Object[]{mHandle, recursive, bufferHasSlices}));
		return bufferHasSlices.getByte(0) != 0;
	}

	/**
	 * unlinks the attached slicestack from this object. If no slice stack is attached, do noting.
	 *
	 * @throws Lib3MFException
	 */
	public void clearSliceStack() throws Lib3MFException {
		mWrapper.checkError(this, mWrapper.lib3mf_object_clearslicestack.invokeInt(new java.lang.Object[]{mHandle}));
	}

	/**
	 * get the Slicestack attached to the object
	 *
	 * @return returns the slicestack instance
	 * @throws Lib3MFException
	 */
	public SliceStack getSliceStack() throws Lib3MFException {
		Pointer bufferSliceStackInstance = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_object_getslicestack.invokeInt(new java.lang.Object[]{mHandle, bufferSliceStackInstance}));
		Pointer valueSliceStackInstance = bufferSliceStackInstance.getPointer(0);
		SliceStack sliceStackInstance = null;
		if (valueSliceStackInstance == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "SliceStackInstance was a null pointer");
		}
		sliceStackInstance = mWrapper.PolymorphicFactory(valueSliceStackInstance, SliceStack.class);
		return sliceStackInstance;
	}

	/**
	 * assigns a slicestack to the object
	 *
	 * @param sliceStackInstance the new slice stack of this Object
	 * @throws Lib3MFException
	 */
	public void assignSliceStack(SliceStack sliceStackInstance) throws Lib3MFException {
		Pointer sliceStackInstanceHandle = null;
		if (sliceStackInstance != null) {
			sliceStackInstanceHandle = sliceStackInstance.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "SliceStackInstance is a null value.");
		}
		mWrapper.checkError(this, mWrapper.lib3mf_object_assignslicestack.invokeInt(new java.lang.Object[]{mHandle, sliceStackInstanceHandle}));
	}


}

