/*++

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 KeyStore extends Base {

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

	/**
	 * Adds a consumer to the keystore
	 *
	 * @param consumerID A unique identifier for the consumer
	 * @param keyID The id of the key of the consumer
	 * @param keyValue The public key for this consumer in PEM format
	 * @return The consumer instance
	 * @throws Lib3MFException
	 */
	public Consumer addConsumer(String consumerID, String keyID, String keyValue) throws Lib3MFException {
		byte[] bytesConsumerID = consumerID.getBytes(StandardCharsets.UTF_8);
		Memory bufferConsumerID = new Memory(bytesConsumerID.length + 1);
		bufferConsumerID.write(0, bytesConsumerID, 0, bytesConsumerID.length);
		bufferConsumerID.setByte(bytesConsumerID.length, (byte)0);
		byte[] bytesKeyID = keyID.getBytes(StandardCharsets.UTF_8);
		Memory bufferKeyID = new Memory(bytesKeyID.length + 1);
		bufferKeyID.write(0, bytesKeyID, 0, bytesKeyID.length);
		bufferKeyID.setByte(bytesKeyID.length, (byte)0);
		byte[] bytesKeyValue = keyValue.getBytes(StandardCharsets.UTF_8);
		Memory bufferKeyValue = new Memory(bytesKeyValue.length + 1);
		bufferKeyValue.write(0, bytesKeyValue, 0, bytesKeyValue.length);
		bufferKeyValue.setByte(bytesKeyValue.length, (byte)0);
		Pointer bufferConsumer = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_addconsumer.invokeInt(new java.lang.Object[]{mHandle, bufferConsumerID, bufferKeyID, bufferKeyValue, bufferConsumer}));
		Pointer valueConsumer = bufferConsumer.getPointer(0);
		Consumer consumer = null;
		if (valueConsumer == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "Consumer was a null pointer");
		}
		consumer = mWrapper.PolymorphicFactory(valueConsumer, Consumer.class);
		return consumer;
	}

	/**
	 * Gets the number of consumers in the keystore
	 *
	 * @return The consumer count
	 * @throws Lib3MFException
	 */
	public long getConsumerCount() throws Lib3MFException {
		Pointer bufferCount = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_getconsumercount.invokeInt(new java.lang.Object[]{mHandle, bufferCount}));
		return bufferCount.getLong(0);
	}

	/**
	 * Get a consumer from the keystore
	 *
	 * @param consumerIndex The index of the consumer
	 * @return The consumer instance
	 * @throws Lib3MFException
	 */
	public Consumer getConsumer(long consumerIndex) throws Lib3MFException {
		Pointer bufferConsumer = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_getconsumer.invokeInt(new java.lang.Object[]{mHandle, consumerIndex, bufferConsumer}));
		Pointer valueConsumer = bufferConsumer.getPointer(0);
		Consumer consumer = null;
		if (valueConsumer == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "Consumer was a null pointer");
		}
		consumer = mWrapper.PolymorphicFactory(valueConsumer, Consumer.class);
		return consumer;
	}

	/**
	 * Removes a consumer from the keystore
	 *
	 * @param consumer The consumer instance to remove
	 * @throws Lib3MFException
	 */
	public void removeConsumer(Consumer consumer) throws Lib3MFException {
		Pointer consumerHandle = null;
		if (consumer != null) {
			consumerHandle = consumer.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "Consumer is a null value.");
		}
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_removeconsumer.invokeInt(new java.lang.Object[]{mHandle, consumerHandle}));
	}

	/**
	 * Finds a consumer by ID
	 *
	 * @param consumerID The ID of the consumer
	 * @return The consumer instance
	 * @throws Lib3MFException
	 */
	public Consumer findConsumer(String consumerID) throws Lib3MFException {
		byte[] bytesConsumerID = consumerID.getBytes(StandardCharsets.UTF_8);
		Memory bufferConsumerID = new Memory(bytesConsumerID.length + 1);
		bufferConsumerID.write(0, bytesConsumerID, 0, bytesConsumerID.length);
		bufferConsumerID.setByte(bytesConsumerID.length, (byte)0);
		Pointer bufferConsumer = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_findconsumer.invokeInt(new java.lang.Object[]{mHandle, bufferConsumerID, bufferConsumer}));
		Pointer valueConsumer = bufferConsumer.getPointer(0);
		Consumer consumer = null;
		if (valueConsumer != Pointer.NULL) {
		  consumer = mWrapper.PolymorphicFactory(valueConsumer, Consumer.class);
		}
		return consumer;
	}

	/**
	 * Gets the number of resource data group in the keysore
	 *
	 * @return The number of resource data available
	 * @throws Lib3MFException
	 */
	public long getResourceDataGroupCount() throws Lib3MFException {
		Pointer bufferCount = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_getresourcedatagroupcount.invokeInt(new java.lang.Object[]{mHandle, bufferCount}));
		return bufferCount.getLong(0);
	}

	/**
	 * Adds a resource data group into the keystore.
	 *
	 * @return The resource data group instance
	 * @throws Lib3MFException
	 */
	public ResourceDataGroup addResourceDataGroup() throws Lib3MFException {
		Pointer bufferResourceDataGroup = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_addresourcedatagroup.invokeInt(new java.lang.Object[]{mHandle, bufferResourceDataGroup}));
		Pointer valueResourceDataGroup = bufferResourceDataGroup.getPointer(0);
		ResourceDataGroup resourceDataGroup = null;
		if (valueResourceDataGroup == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceDataGroup was a null pointer");
		}
		resourceDataGroup = mWrapper.PolymorphicFactory(valueResourceDataGroup, ResourceDataGroup.class);
		return resourceDataGroup;
	}

	/**
	 * Gets a resource data group
	 *
	 * @param resourceDataIndex The index of the resource data
	 * @return The resource data group instance
	 * @throws Lib3MFException
	 */
	public ResourceDataGroup getResourceDataGroup(long resourceDataIndex) throws Lib3MFException {
		Pointer bufferResourceDataGroup = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_getresourcedatagroup.invokeInt(new java.lang.Object[]{mHandle, resourceDataIndex, bufferResourceDataGroup}));
		Pointer valueResourceDataGroup = bufferResourceDataGroup.getPointer(0);
		ResourceDataGroup resourceDataGroup = null;
		if (valueResourceDataGroup == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceDataGroup was a null pointer");
		}
		resourceDataGroup = mWrapper.PolymorphicFactory(valueResourceDataGroup, ResourceDataGroup.class);
		return resourceDataGroup;
	}

	/**
	 * Removes a resource data group
	 *
	 * @param resourceDataGroup The resource data group instance
	 * @throws Lib3MFException
	 */
	public void removeResourceDataGroup(ResourceDataGroup resourceDataGroup) throws Lib3MFException {
		Pointer resourceDataGroupHandle = null;
		if (resourceDataGroup != null) {
			resourceDataGroupHandle = resourceDataGroup.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceDataGroup is a null value.");
		}
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_removeresourcedatagroup.invokeInt(new java.lang.Object[]{mHandle, resourceDataGroupHandle}));
	}

	/**
	 * Finds a resource data group that contains a particular resourcedata
	 *
	 * @param partPath The target path for the resourcedata hold by the resource data group
	 * @return The data resource instance
	 * @throws Lib3MFException
	 */
	public ResourceDataGroup findResourceDataGroup(PackagePart partPath) throws Lib3MFException {
		Pointer partPathHandle = null;
		if (partPath != null) {
			partPathHandle = partPath.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "PartPath is a null value.");
		}
		Pointer bufferResourceDataGroup = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_findresourcedatagroup.invokeInt(new java.lang.Object[]{mHandle, partPathHandle, bufferResourceDataGroup}));
		Pointer valueResourceDataGroup = bufferResourceDataGroup.getPointer(0);
		ResourceDataGroup resourceDataGroup = null;
		if (valueResourceDataGroup != Pointer.NULL) {
		  resourceDataGroup = mWrapper.PolymorphicFactory(valueResourceDataGroup, ResourceDataGroup.class);
		}
		return resourceDataGroup;
	}

	/**
	 * Add resourcedata to resourcedatagroup element
	 *
	 * @param resourceDataGroup The resource data group where to add this resource data
	 * @param partPath The path of the part to be encrypted
	 * @param algorithm The encryption algorithm to be used to encrypt this resource
	 * @param compression Whether compression should be used prior to encryption
	 * @param additionalAuthenticationData Additional data to be encrypted along the contents for better security
	 * @return The data resource instance
	 * @throws Lib3MFException
	 */
	public ResourceData addResourceData(ResourceDataGroup resourceDataGroup, PackagePart partPath, Lib3MFWrapper.EncryptionAlgorithm algorithm, Lib3MFWrapper.Compression compression, byte[] additionalAuthenticationData) throws Lib3MFException {
		Pointer resourceDataGroupHandle = null;
		if (resourceDataGroup != null) {
			resourceDataGroupHandle = resourceDataGroup.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceDataGroup is a null value.");
		}
		Pointer partPathHandle = null;
		if (partPath != null) {
			partPathHandle = partPath.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "PartPath is a null value.");
		}
		Pointer bufferAdditionalAuthenticationData = new Memory(Math.max(1, 1 * additionalAuthenticationData.length));
		for (int i = 0; i < additionalAuthenticationData.length; i++) {
		  bufferAdditionalAuthenticationData.setByte(1 * i, additionalAuthenticationData[i]);
		}
		Pointer bufferResourceData = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_addresourcedata.invokeInt(new java.lang.Object[]{mHandle, resourceDataGroupHandle, partPathHandle, Lib3MFWrapper.EnumConversion.convertEncryptionAlgorithmToConst(algorithm), Lib3MFWrapper.EnumConversion.convertCompressionToConst(compression), (long) additionalAuthenticationData.length, bufferAdditionalAuthenticationData, bufferResourceData}));
		Pointer valueResourceData = bufferResourceData.getPointer(0);
		ResourceData resourceData = null;
		if (valueResourceData == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceData was a null pointer");
		}
		resourceData = mWrapper.PolymorphicFactory(valueResourceData, ResourceData.class);
		return resourceData;
	}

	/**
	 * Removes a resource data
	 *
	 * @param resourceData The resource data to be removed
	 * @throws Lib3MFException
	 */
	public void removeResourceData(ResourceData resourceData) throws Lib3MFException {
		Pointer resourceDataHandle = null;
		if (resourceData != null) {
			resourceDataHandle = resourceData.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceData is a null value.");
		}
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_removeresourcedata.invokeInt(new java.lang.Object[]{mHandle, resourceDataHandle}));
	}

	/**
	 * Finds a resource data on this resource group
	 *
	 * @param resourcePath The target path for the resourcedata
	 * @return The resource data instance
	 * @throws Lib3MFException
	 */
	public ResourceData findResourceData(PackagePart resourcePath) throws Lib3MFException {
		Pointer resourcePathHandle = null;
		if (resourcePath != null) {
			resourcePathHandle = resourcePath.getHandle();
		} else {
			throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourcePath is a null value.");
		}
		Pointer bufferResourceData = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_findresourcedata.invokeInt(new java.lang.Object[]{mHandle, resourcePathHandle, bufferResourceData}));
		Pointer valueResourceData = bufferResourceData.getPointer(0);
		ResourceData resourceData = null;
		if (valueResourceData != Pointer.NULL) {
		  resourceData = mWrapper.PolymorphicFactory(valueResourceData, ResourceData.class);
		}
		return resourceData;
	}

	/**
	 * Gets the number of resource data in the keysore
	 *
	 * @return The number of resource data available
	 * @throws Lib3MFException
	 */
	public long getResourceDataCount() throws Lib3MFException {
		Pointer bufferCount = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_getresourcedatacount.invokeInt(new java.lang.Object[]{mHandle, bufferCount}));
		return bufferCount.getLong(0);
	}

	/**
	 * Gets a resource data
	 *
	 * @param resourceDataIndex The index of the resource data
	 * @return The data resource instance
	 * @throws Lib3MFException
	 */
	public ResourceData getResourceData(long resourceDataIndex) throws Lib3MFException {
		Pointer bufferResourceData = new Memory(8);
		mWrapper.checkError(this, mWrapper.lib3mf_keystore_getresourcedata.invokeInt(new java.lang.Object[]{mHandle, resourceDataIndex, bufferResourceData}));
		Pointer valueResourceData = bufferResourceData.getPointer(0);
		ResourceData resourceData = null;
		if (valueResourceData == Pointer.NULL) {
		  throw new Lib3MFException(Lib3MFException.LIB3MF_ERROR_INVALIDPARAM, "ResourceData was a null pointer");
		}
		resourceData = mWrapper.PolymorphicFactory(valueResourceData, ResourceData.class);
		return resourceData;
	}

	/**
	 * Gets the keystore UUID
	 *
	 * @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_keystore_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_keystore_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 keystore has a UUID
		 */
		public boolean HasUUID;

		/**
		 * returns the keystore uuid.
		 */
		public String UUID;

	}
	/**
	 * Sets the keystore UUID
	 *
	 * @param uUID The new keystore uuid.
	 * @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_keystore_setuuid.invokeInt(new java.lang.Object[]{mHandle, bufferUUID}));
	}


}

