//--------------------------------------------------------------------------------------------------
// Copyright (c) id3 Technologies
// All Rights Reserved.
//--------------------------------------------------------------------------------------------------
#pragma once
#include <id3BiosealCppWrapper/id3BiosealException.hpp>
#include <id3BiosealCppWrapper/id3BiosealStringArray.hpp>
#include <id3Bioseal/id3BiosealDecryptionArgs.h>
#include "vector"

namespace id3BiosealCppWrapper
{

/**
 * Represents the arguments to the decryption callback.
 */
class DecryptionArgs
{
private:
    ID3_BIOSEAL_DECRYPTION_ARGS handle_{};

public:
    DecryptionArgs() {
        check_error(id3BiosealDecryptionArgs_Initialize(&handle_));
    }

    virtual ~DecryptionArgs() {
        if (handle_) {
            id3BiosealDecryptionArgs_Dispose(&handle_);
        }
    }


    DecryptionArgs(DecryptionArgs &&src) noexcept: handle_(src.handle_) {
        src.handle_ = nullptr;
    }

    ID3_BIOSEAL_DECRYPTION_ARGS getHandle() const { return handle_; }
    operator ID3_BIOSEAL_DECRYPTION_ARGS () const { return handle_; }

    // public getters and setters
    /**
    * Gets the the name of the field to decrypt.
    * @param fieldName [out] The name of the field to decrypt.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The name of the field to decrypt.
    */
    void getFieldName(std::string & fieldName) {
        int fieldNameSize = -1;
        auto err = id3BiosealDecryptionArgs_GetFieldName(handle_, fieldName.data(), &fieldNameSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            fieldName.resize(fieldNameSize);
            err = id3BiosealDecryptionArgs_GetFieldName(handle_, fieldName.data(), &fieldNameSize);
            if (err == 0) { fieldName.resize(fieldNameSize); }
        }
        check_error(err);
    }

    /**
    * Gets the the name of the field to decrypt.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The name of the field to decrypt.
    */
    std::string getFieldName() {
        std::string field_name;
        getFieldName(field_name);
        return field_name;
    }

    /**
    * Gets the the data to decrypt as a binary array.
    * @param inputData [out] The data to decrypt as a binary array.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The data to decrypt as a binary array.
    */
    void getInputData(std::vector<unsigned char> & inputData) {
        int inputDataSize = -1;
        auto err = id3BiosealDecryptionArgs_GetInputData(handle_, inputData.data(), &inputDataSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            inputData.resize(inputDataSize);
            err = id3BiosealDecryptionArgs_GetInputData(handle_, inputData.data(), &inputDataSize);
        }
        check_error(err);
    }

    /**
    * Gets the the data to decrypt as a binary array.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The data to decrypt as a binary array.
    */
    std::vector<unsigned char> getInputData() {
        std::vector<unsigned char> input_data;
        getInputData(input_data);
        return input_data;
    }

    /**
    * Gets the the decrypted data as a binary array.
    * @param outputData [out] The decrypted data as a binary array.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The decrypted data as a binary array.
    */
    void getOutputData(std::vector<unsigned char> & outputData) {
        int outputDataSize = -1;
        auto err = id3BiosealDecryptionArgs_GetOutputData(handle_, outputData.data(), &outputDataSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            outputData.resize(outputDataSize);
            err = id3BiosealDecryptionArgs_GetOutputData(handle_, outputData.data(), &outputDataSize);
        }
        check_error(err);
    }

    /**
    * Gets the the decrypted data as a binary array.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The decrypted data as a binary array.
    */
    std::vector<unsigned char> getOutputData() {
        std::vector<unsigned char> output_data;
        getOutputData(output_data);
        return output_data;
    }

    /**
    * Sets the the decrypted data as a binary array.
    * @param outputData [in] The decrypted data as a binary array.
    * @param outputDataSize [in] Size of the 'outputData' buffer.
    * @exception BiosealException An error has occured during Bioseal library execution.
    */
    void setOutputData(unsigned char *outputData, int outputDataSize) {
        check_error(id3BiosealDecryptionArgs_SetOutputData(handle_, outputData, outputDataSize));
    }

    /**
    * Gets the gets a string list containing the keys in the dict.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval Gets a string list containing the keys in the dict.
    */
    StringArray getKeys() {
        StringArray keys;
        check_error(id3BiosealDecryptionArgs_GetKeys(handle_, keys));
        return keys;
    }

    // public methods
    /**
    * Gets an item of the DecryptionArgs object.
    * @param key [in] Unique key of the  item to get.
    * @param item [out]  item to get.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval  item to get.
    */
    void get(const char *key, std::string & item) {
        int itemSize = -1;
        auto err = id3BiosealDecryptionArgs_Get(handle_, key, item.data(), &itemSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            item.resize(itemSize);
            err = id3BiosealDecryptionArgs_Get(handle_, key, item.data(), &itemSize);
            if (err == 0) { item.resize(itemSize); }
        }
        check_error(err);
    }

    /**
    * Gets an item of the DecryptionArgs object.
    * @param key [in] Unique key of the  item to get.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval  item to get.
    */
    std::string get(const char *key) {
        std::string item;
        get(key, item);
        return item;
    }

    /**
    * Gets the number of elements in the DecryptionArgs object.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval Number of elements in the  object.
    */
    int getCount() {
        int count;
        check_error(id3BiosealDecryptionArgs_GetCount(handle_, &count));
        return count;
    }

    /**
    * Determines whether the DecryptionArgsobject contains the specified key.
    * @param key [in] The key to locate in the  object.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval true if the  object contains an element with the specified key, otherwise false.
    */
    bool containsKey(const char *key) {
        bool result;
        check_error(id3BiosealDecryptionArgs_ContainsKey(handle_, key, &result));
        return result;
    }

};
};