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

namespace id3BiosealCppWrapper
{

/**
 * Contains resource callback data.
 */
class ResourceCallbackArgs
{
private:
    ID3_BIOSEAL_RESOURCE_CALLBACK_ARGS handle_{};

public:
    ResourceCallbackArgs() {
        check_error(id3BiosealResourceCallbackArgs_Initialize(&handle_));
    }

    virtual ~ResourceCallbackArgs() {
        if (handle_) {
            id3BiosealResourceCallbackArgs_Dispose(&handle_);
        }
    }


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

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

    // public getters and setters
    /**
    * Gets the the URI used to retrieve the external resource.
    * @param uri [out] The URI used to retrieve the external resource.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The URI used to retrieve the external resource.
    */
    void getUri(std::string & uri) {
        int uriSize = -1;
        auto err = id3BiosealResourceCallbackArgs_GetUri(handle_, uri.data(), &uriSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            uri.resize(uriSize);
            err = id3BiosealResourceCallbackArgs_GetUri(handle_, uri.data(), &uriSize);
            if (err == 0) { uri.resize(uriSize); }
        }
        check_error(err);
    }

    /**
    * Gets the the URI used to retrieve the external resource.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The URI used to retrieve the external resource.
    */
    std::string getUri() {
        std::string uri;
        getUri(uri);
        return uri;
    }

    /**
    * Gets the the resource name corresponing to the uri.
    * @param resourceName [out] The resource name corresponing to the uri.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The resource name corresponing to the uri.
    */
    void getResourceName(std::string & resourceName) {
        int resourceNameSize = -1;
        auto err = id3BiosealResourceCallbackArgs_GetResourceName(handle_, resourceName.data(), &resourceNameSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            resourceName.resize(resourceNameSize);
            err = id3BiosealResourceCallbackArgs_GetResourceName(handle_, resourceName.data(), &resourceNameSize);
            if (err == 0) { resourceName.resize(resourceNameSize); }
        }
        check_error(err);
    }

    /**
    * Gets the the resource name corresponing to the uri.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The resource name corresponing to the uri.
    */
    std::string getResourceName() {
        std::string resource_name;
        getResourceName(resource_name);
        return resource_name;
    }

    /**
    * Gets the the resource type corresponding to the uri.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The resource type corresponding to the uri.
    */
    id3BiosealResourceType getResourceType() {
        id3BiosealResourceType resource_type;
        check_error(id3BiosealResourceCallbackArgs_GetResourceType(handle_, &resource_type));
        return resource_type;
    }

    /**
    * Gets the the external resource data must be updated.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The external resource data must be updated.
    */
    bool getRequiresUpdate() {
        bool requires_update;
        check_error(id3BiosealResourceCallbackArgs_GetRequiresUpdate(handle_, &requires_update));
        return requires_update;
    }

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

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

    /**
    * Sets the the external resource data as a byte array.
    * @param outputData [in] The external resource data as a byte 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(id3BiosealResourceCallbackArgs_SetOutputData(handle_, outputData, outputDataSize));
    }

    // public methods
    /**
    * Downloads a resource.
    * @exception BiosealException An error has occured during Bioseal library execution.
    */
    void download() {
        check_error(id3BiosealResourceCallbackArgs_Download(handle_));
    }

    /**
    * Downloads a file from the specified URL and returns a string.
    * @param url [in] The URL to the file.
    * @param data [out] The file as a string.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The file as a string.
    */
    void downloadStringFile(const char *url, std::string & data) {
        int dataSize = -1;
        auto err = id3BiosealResourceCallbackArgs_DownloadStringFile(handle_, url, data.data(), &dataSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            data.resize(dataSize);
            err = id3BiosealResourceCallbackArgs_DownloadStringFile(handle_, url, data.data(), &dataSize);
            if (err == 0) { data.resize(dataSize); }
        }
        check_error(err);
    }

    /**
    * Downloads a file from the specified URL and returns a string.
    * @param url [in] The URL to the file.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The file as a string.
    */
    std::string downloadStringFile(const char *url) {
        std::string data;
        downloadStringFile(url, data);
        return data;
    }

    /**
    * Computes the SHA-256 of the external resource's data.
    * @param result [out] A string that contains the SHA-256.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval A string that contains the SHA-256.
    */
    void computeSha256(std::string & result) {
        int resultSize = -1;
        auto err = id3BiosealResourceCallbackArgs_ComputeSha256(handle_, result.data(), &resultSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            result.resize(resultSize);
            err = id3BiosealResourceCallbackArgs_ComputeSha256(handle_, result.data(), &resultSize);
            if (err == 0) { result.resize(resultSize); }
        }
        check_error(err);
    }

    /**
    * Computes the SHA-256 of the external resource's data.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval A string that contains the SHA-256.
    */
    std::string computeSha256() {
        std::string result;
        computeSha256(result);
        return result;
    }

};
};