#include <stdarg.h>

#include "tc_private/tc_handle.h"
#include "tc_private/tc_private.h"

#include "log/log.h"

#include "tc_tpm2.h"
#include "tpm2_common.h"

#include "tc_type.h"
#include "tc_errcode.h"

struct tpm2_end_ctx
{
    TC_HANDLE           *handle;
};

TC_RC tpm2_end_init(struct api_ctx_st *api_ctx, int num, ...){
    TC_RC rc = TC_SUCCESS;

    struct tpm2_end_ctx* ectx = (struct tpm2_end_ctx*)malloc(sizeof(struct tpm2_end_ctx));

    va_list ap;
    va_start(ap, num);
    ectx->handle = va_arg(ap, TC_HANDLE*);
    va_end(ap);

    api_ctx->data = (HANDLE_DATA*)ectx;

    return rc;
}

TC_RC tpm2_end_free(struct api_ctx_st *api_ctx){
    TC_RC rc = TC_SUCCESS;  
    struct tpm2_end_ctx* ectx = (struct tpm2_end_ctx*)api_ctx->data;\
    TC_HANDLE_CTX* tc_handle_ctx = (TC_HANDLE_CTX*)(*ectx->handle);

    for (int i = 0; i < tc_handle_ctx->handle.tc_object->count; i++)
    {
        if (tc_handle_ctx->handle.tc_object->node_info[i]->obj_private != NULL) 
            free(tc_handle_ctx->handle.tc_object->node_info[i]->obj_private);
        if (tc_handle_ctx->handle.tc_object->node_info[i]->obj_public != NULL)
            free(tc_handle_ctx->handle.tc_object->node_info[i]->obj_public);
        if (tc_handle_ctx->handle.tc_object->node_info[i]->obj_name)
            free(tc_handle_ctx->handle.tc_object->node_info[i]->obj_name);
        free(tc_handle_ctx->handle.tc_object->node_info[i]);
    }
    free(tc_handle_ctx->handle.tc_object);
    // free(tc_handle_ctx);
    free(api_ctx->data);  
    api_ctx->data = NULL;
    api_ctx->cmd_code = API_NULL;
    return rc;
}

TC_RC tpm2_end(API_CTX *ctx){
    TC_RC rc = TC_SUCCESS;

    struct tpm2_end_ctx* ectx = (struct tpm2_end_ctx*)ctx->data;

    TC_HANDLE_CTX* tc_handle_ctx = (TC_HANDLE_CTX*)(*ectx->handle);

    for (int i = 0; i < tc_handle_ctx->handle.tc_object->count; i++)
    {
        rc = tpm2_flush_context((TSS2_SYS_CONTEXT*)tc_handle_ctx->handle.tc_context,
                                tc_handle_ctx->handle.tc_object->node_info[i]->obj_handle);
        if (rc != TSS2_RC_SUCCESS) {
            log_error("Failed to run flush_context:0x%0x\n", rc);
            rc = TC_COMMAND_END;
        } 
    }
    rc = tpm2_free((TSS2_SYS_CONTEXT*)tc_handle_ctx->handle.tc_context);
    if (rc != TSS2_RC_SUCCESS) {
        log_error("Failed to run api_end:0x%0x\n", rc);
        rc = TC_COMMAND_END;
    }
    return  rc;
}