#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#include "tlc_basedef.h"
#include "tlc_process.h"

#include "tlc_tal_operation.h"
#include "tlc_dbg.h"


#ifdef __cplusplus
extern "C"
{
#endif


typedef enum {
    AUTHNR_STATE_NONE,
    AUTHNR_STATE_IDLE,
    AUTHNR_STATE_PROCESS,
} AuthnrState;

static AuthnrState gAuthnrState;
pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;

uint32 initialize()
{
    AuthnrResult ret = AUTHNR_SUCCESS;
    printI("initialize. state:%d", gAuthnrState);

    pthread_mutex_lock(&gMutex);
    do {
        ret = gTal.initialize();
        if (ret != AUTHNR_SUCCESS) {
            printE("TZ session open fail. ret:%d", ret);
            break;
        }
        gAuthnrState = AUTHNR_STATE_IDLE;
    } while (0);
    pthread_mutex_unlock(&gMutex);

    return (uint32)ret;
}


uint32 terminate()
{
    AuthnrResult ret = AUTHNR_SUCCESS;
    printI("terminate. state:%d", gAuthnrState);

    if (gAuthnrState != AUTHNR_STATE_IDLE) {
        printI("can not terminate. not error");
        return AUTHNR_ERROR_NOT_PREPARED;
    }

    pthread_mutex_lock(&gMutex);
    do {
        ret = gTal.terminate();
        if (ret != 0) {
            printE("TZ session close fail. ret:%d", ret);
            break;
        }
        gAuthnrState = AUTHNR_STATE_NONE;
    } while (0);
    pthread_mutex_unlock(&gMutex);

    return (uint32)ret;
}


uint32 process(const BlobData* pBlobInput, BlobData* pBlobOutput)
{
    AuthnrResult ret = AUTHNR_SUCCESS;
    BlobData blobBuf = {0};

    printI("process. state:%d", gAuthnrState);

    if (gAuthnrState != AUTHNR_STATE_IDLE) {
        printE("not initialized");
        return AUTHNR_ERROR_NOT_PREPARED;
    }

    if (pBlobInput->length > MAX_BLOB_DATA_SIZE) {
        printE("Invalid input data size. input data size: %d, Max blob data size:%d", pBlobInput->length, MAX_BLOB_DATA_SIZE);
        return AUTHNR_ERROR_BUF_TOO_SMALL;
    }

    pthread_mutex_lock(&gMutex);
    do {
        gAuthnrState = AUTHNR_STATE_PROCESS;
        ret = gTal.process(pBlobInput, pBlobOutput);
        if (ret != AUTHNR_SUCCESS) {
            printE("process Error. ret:%d", ret);
        }
        gAuthnrState = AUTHNR_STATE_IDLE;
    } while (0);
    pthread_mutex_unlock(&gMutex);

    return (uint32)ret;
}


#ifdef __cplusplus
}
#endif

