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

namespace id3BiosealCppWrapper
{

/**
 * Provides information about the manifest.
 */
class Manifest
{
private:
    ID3_BIOSEAL_MANIFEST handle_{};

public:
    Manifest() {
        check_error(id3BiosealManifest_Initialize(&handle_));
    }

    virtual ~Manifest() {
        if (handle_) {
            id3BiosealManifest_Dispose(&handle_);
        }
    }


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

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

    // public getters and setters
    /**
    * Gets the the manifest ID in ISO 22385 format.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The manifest ID in ISO 22385 format.
    */
    int getManifestId() {
        int manifest_id;
        check_error(id3BiosealManifest_GetManifestId(handle_, &manifest_id));
        return manifest_id;
    }

    /**
    * Gets the the manifest version.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The manifest version.
    */
    int getManifestVersion() {
        int manifest_version;
        check_error(id3BiosealManifest_GetManifestVersion(handle_, &manifest_version));
        return manifest_version;
    }

    /**
    * Gets the the list of supported languages declared in the manifest.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The list of supported languages declared in the manifest.
    */
    StringArray getSupportedLanguages() {
        StringArray supported_languages;
        check_error(id3BiosealManifest_GetSupportedLanguages(handle_, supported_languages));
        return supported_languages;
    }

    /**
    * Gets the the extension list.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The extension list.
    */
    ExtensionList getExtensionList() {
        ExtensionList extension_list;
        check_error(id3BiosealManifest_GetExtensionList(handle_, extension_list));
        return extension_list;
    }

    /**
    * Gets the the log.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The log.
    */
    Log getLog() {
        Log log;
        check_error(id3BiosealManifest_GetLog(handle_, log));
        return log;
    }

    /**
    * Sets the the log.
    * @param log [in] The log.
    * @exception BiosealException An error has occured during Bioseal library execution.
    */
    void setLog(const Log & log) {
        check_error(id3BiosealManifest_SetLog(handle_, log));
    }

    // public methods
    /**
    * Loads the manifest.
    * @param manifestData [in] The manifest data.
    * @param manifestDataSize [in] Size of the 'manifestData' buffer.
    * @exception BiosealException An error has occured during Bioseal library execution.
    */
    void load(unsigned char *manifestData, int manifestDataSize) {
        check_error(id3BiosealManifest_Load(handle_, manifestData, manifestDataSize));
    }

    /**
    * Loads the manifest.
    * @param manifestData [in] The manifest data.
    * @exception BiosealException An error has occured during Bioseal library execution.
    */
    void loadFromString(const char *manifestData) {
        check_error(id3BiosealManifest_LoadFromString(handle_, manifestData));
    }

    /**
    * Loads the manifest from file.
    * @param path [in] The manifest path.
    * @exception BiosealException An error has occured during Bioseal library execution.
    */
    void loadFromFile(const char *path) {
        check_error(id3BiosealManifest_LoadFromFile(handle_, path));
    }

    /**
    * Gets the name of the document.
    * @param language [in] The expected language.
    * @param documentName [out] The name of the document.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The name of the document.
    */
    void getDocumentName(const char *language, std::string & documentName) {
        int documentNameSize = -1;
        auto err = id3BiosealManifest_GetDocumentName(handle_, language, documentName.data(), &documentNameSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            documentName.resize(documentNameSize);
            err = id3BiosealManifest_GetDocumentName(handle_, language, documentName.data(), &documentNameSize);
            if (err == 0) { documentName.resize(documentNameSize); }
        }
        check_error(err);
    }

    /**
    * Gets the name of the document.
    * @param language [in] The expected language.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The name of the document.
    */
    std::string getDocumentName(const char *language) {
        std::string document_name;
        getDocumentName(language, document_name);
        return document_name;
    }

    /**
    * Gets the description of the document.
    * @param language [in] The expected language.
    * @param documentDescription [out] The description of the document.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The description of the document.
    */
    void getDocumentDescription(const char *language, std::string & documentDescription) {
        int documentDescriptionSize = -1;
        auto err = id3BiosealManifest_GetDocumentDescription(handle_, language, documentDescription.data(), &documentDescriptionSize);
        if (err == (int)id3BiosealError_InsufficientBuffer) {
            documentDescription.resize(documentDescriptionSize);
            err = id3BiosealManifest_GetDocumentDescription(handle_, language, documentDescription.data(), &documentDescriptionSize);
            if (err == 0) { documentDescription.resize(documentDescriptionSize); }
        }
        check_error(err);
    }

    /**
    * Gets the description of the document.
    * @param language [in] The expected language.
    * @exception BiosealException An error has occured during Bioseal library execution.
    * @retval The description of the document.
    */
    std::string getDocumentDescription(const char *language) {
        std::string document_description;
        getDocumentDescription(language, document_description);
        return document_description;
    }

};
};