#include "sha256_help.h"
#include "v2g_context.h"
#include "openssl_utils.h"
#include "hmac_sha256.h"
#include "base64.h"

void sha256_signature_from_DigestValue(uint8_t *digest, struct iso2_AuthorizationReqType* req)
{
    memset(digest, 0, SHA256_SIGNATURE_SIZE);

    struct iso2_exiFragment iso2_fragment;
    init_iso2_exiFragment(&iso2_fragment);

    iso2_fragment.AuthorizationReq_isUsed = 1u;
    memcpy(&iso2_fragment.AuthorizationReq, req, sizeof(*req));

    exi_bitstream_t stream;
    uint8_t exi_buffer[MAX_EXI_SIZE];
    exi_bitstream_init(&stream, exi_buffer, MAX_EXI_SIZE, 0, NULL);
    int err = encode_iso2_exiFragment(&stream, &iso2_fragment);
    if (err == 0)
    {
        sha256_ctx_t hash;
        sha256_init(&hash);
        const size_t frag_data_len = exi_bitstream_get_length(&stream);
        sha256_update(&hash, exi_buffer, frag_data_len);
        sha256_final(&hash, digest);
        // base64_encode(digest, exi_buffer, SHA256_SIGNATURE_SIZE);
    }
}

void sha256_signature_from_SignedInfo(uint8_t *digest, const struct iso2_SignatureType* iso2_signature)
{
    memset(digest, 0, SHA256_SIGNATURE_SIZE);

    struct iso2_xmldsigFragment sig_fragment;
    init_iso2_xmldsigFragment(&sig_fragment);

    sig_fragment.SignedInfo_isUsed = 1;
    sig_fragment.SignedInfo = iso2_signature->SignedInfo;

    /** \req [V2G2-771] Don't use following fields */
    sig_fragment.SignedInfo.Id_isUsed = 0;
    sig_fragment.SignedInfo.CanonicalizationMethod.ANY_isUsed = 0;
    sig_fragment.SignedInfo.SignatureMethod.HMACOutputLength_isUsed = 0;
    sig_fragment.SignedInfo.SignatureMethod.ANY_isUsed = 0;
    for (struct iso2_ReferenceType* ref = sig_fragment.SignedInfo.Reference.array; ref != (sig_fragment.SignedInfo.Reference.array + sig_fragment.SignedInfo.Reference.arrayLen); ++ref) 
    {
        ref->Type_isUsed = 0;
        ref->Transforms.Transform.ANY_isUsed = 0;
        ref->Transforms.Transform.XPath_isUsed = 0;
        ref->DigestMethod.ANY_isUsed = 0;
    }
    exi_bitstream_t stream;
    uint8_t exi_buffer[MAX_EXI_SIZE];
    exi_bitstream_init(&stream, exi_buffer, MAX_EXI_SIZE, 0, NULL);
    int err = encode_iso2_xmldsigFragment(&stream, &sig_fragment);
    if (err == 0)
    {
        sha256_ctx_t hash;
        sha256_init(&hash);
        const size_t frag_data_len = exi_bitstream_get_length(&stream);
        sha256_update(&hash, exi_buffer, frag_data_len);
        sha256_final(&hash, digest);
        // base64_encode(digest, exi_buffer, SHA256_SIGNATURE_SIZE);
    }
}
