/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */

#include <open62541/client_config_default.h>
#include <open62541/client_highlevel_async.h>
#include <open62541/client_subscriptions.h>
#include <open62541/plugin/log_stdout.h>
#include <open62541/server_config_default.h>

#include <stdlib.h>

#define NODES_EXIST
/* async connection callback, it only gets called after the completion of the whole
 * connection process*/
static void
onConnect(UA_Client *client, void *userdata, UA_UInt32 requestId,
          void *status) {
    printf("Async connect returned with status code %s\n",
           UA_StatusCode_name(*(UA_StatusCode *) status));
}

static
void
fileBrowsed(UA_Client *client, void *userdata, UA_UInt32 requestId,
            UA_BrowseResponse *response) {
    printf("%-50s%i\n", "Received BrowseResponse for request ", requestId);
    UA_String us = *(UA_String *) userdata;
    printf("---%.*s passed safely \n", (int) us.length, us.data);
}

/*high-level function callbacks*/
static
void
readValueAttributeCallback(UA_Client *client, void *userdata,
                           UA_UInt32 requestId, UA_Variant *var) {
    printf("%-50s%i\n", "Read value attribute for request", requestId);

    if(UA_Variant_hasScalarType(var, &UA_TYPES[UA_TYPES_INT32])) {
        UA_Int32 int_val = *(UA_Int32*) var->data;
        printf("---%-40s%-8i\n",
               "Reading the value of node (1, \"the.answer\"):", int_val);
    }

    /*more type distinctions possible*/
    return;
}

static
void
attrWritten(UA_Client *client, void *userdata, UA_UInt32 requestId,
            UA_WriteResponse *response) {
    /*assuming no data to be retrieved by writing attributes*/
    printf("%-50s%i\n", "Wrote value attribute for request ", requestId);
    UA_WriteResponse_clear(response);
}

#ifdef NODES_EXIST
#ifdef UA_ENABLE_METHODCALLS
static void
methodCalled(UA_Client *client, void *userdata, UA_UInt32 requestId,
             UA_CallResponse *response) {

    printf("%-50s%i\n", "Called method for request ", requestId);
    size_t outputSize;
    UA_Variant *output;
    UA_StatusCode retval = response->responseHeader.serviceResult;
    if(retval == UA_STATUSCODE_GOOD) {
        if(response->resultsSize == 1)
            retval = response->results[0].statusCode;
        else
            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
    }
    if(retval != UA_STATUSCODE_GOOD) {
        UA_CallResponse_clear(response);
    }

    /* Move the output arguments */
    output = response->results[0].outputArguments;
    outputSize = response->results[0].outputArgumentsSize;
    response->results[0].outputArguments = NULL;
    response->results[0].outputArgumentsSize = 0;

    if(retval == UA_STATUSCODE_GOOD) {
        printf("---Method call was successful, returned %lu values.\n",
               (unsigned long) outputSize);
        UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
    } else {
        printf("---Method call was unsuccessful, returned %x values.\n",
                retval);
    }
    UA_CallResponse_clear(response);
}

static void
translateCalled(UA_Client *client, void *userdata, UA_UInt32 requestId,
                UA_TranslateBrowsePathsToNodeIdsResponse *response) {
    printf("%-50s%i\n", "Translated path for request ", requestId);

    if(response->results[0].targetsSize == 1)
        return;
    UA_TranslateBrowsePathsToNodeIdsResponse_clear(response);
}
#endif /* UA_ENABLE_METHODCALLS */
#endif

int
main(int argc, char *argv[]) {
    UA_Client *client = UA_Client_new();
    UA_ClientConfig_setDefault(UA_Client_getConfig(client));
    UA_UInt32 reqId = 0;
    UA_String userdata = UA_STRING("userdata");

    UA_BrowseRequest bReq;
    UA_BrowseRequest_init(&bReq);
    bReq.requestedMaxReferencesPerNode = 0;
    bReq.nodesToBrowse = UA_BrowseDescription_new();
    bReq.nodesToBrowseSize = 1;
    bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
    bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */

    UA_Client_connect_async(client, "opc.tcp://localhost:4840", onConnect, NULL);

    /*Windows needs time to response*/
    UA_sleep_ms(100);

    /* What happens if client tries to send request before connected? */
    UA_Client_sendAsyncBrowseRequest(client, &bReq, fileBrowsed, &userdata, &reqId);

    UA_DateTime startTime = UA_DateTime_nowMonotonic();
    do {
        /*TODO: fix memory-related bugs if condition not checked*/
        if(UA_Client_getState(client) == UA_CLIENTSTATE_SESSION) {
            /* If not connected requests are not sent */
            UA_Client_sendAsyncBrowseRequest(client, &bReq, fileBrowsed, &userdata, &reqId);
        }
        /* Requests are processed */
        UA_BrowseRequest_clear(&bReq);
        UA_Client_run_iterate(client, 0);
        UA_sleep_ms(100);

        /* Break loop if server cannot be connected within 2s -- prevents build timeout */
        if(UA_DateTime_nowMonotonic() - startTime > 2000 * UA_DATETIME_MSEC)
            break;
    } while(reqId < 10);

    /* Demo: high-level functions */
    UA_Int32 value = 0;
    UA_Variant myVariant;
    UA_Variant_init(&myVariant);

    UA_Variant input;
    UA_Variant_init(&input);

    for(UA_UInt16 i = 0; i < 5; i++) {
        if(UA_Client_getState(client) == UA_CLIENTSTATE_SESSION) {
            /* writing and reading value 1 to 5 */
            UA_Variant_setScalarCopy(&myVariant, &value, &UA_TYPES[UA_TYPES_INT32]);
            value++;
            UA_Client_writeValueAttribute_async(client,
                                                UA_NODEID_STRING(1, "the.answer"),
                                                &myVariant, attrWritten, NULL,
                                                &reqId);
            UA_Variant_clear(&myVariant);

            UA_Client_readValueAttribute_async(client,
                                               UA_NODEID_STRING(1, "the.answer"),
                                               readValueAttributeCallback, NULL,
                                               &reqId);

//TODO: check the existance of the nodes inside these functions (otherwise seg faults)
#ifdef NODES_EXIST
#ifdef UA_ENABLE_METHODCALLS
            UA_String stringValue = UA_String_fromChars("World");
            UA_Variant_setScalar(&input, &stringValue, &UA_TYPES[UA_TYPES_STRING]);

            UA_Client_call_async(client,
                                 UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                                 UA_NODEID_NUMERIC(1, 62541), 1, &input,
                                 methodCalled, NULL, &reqId);
            UA_String_clear(&stringValue);

    #define pathSize 3
            char *paths[pathSize] = { "Server", "ServerStatus", "State" };
            UA_UInt32 ids[pathSize] = { UA_NS0ID_ORGANIZES,
            UA_NS0ID_HASCOMPONENT, UA_NS0ID_HASCOMPONENT };

            UA_Cient_translateBrowsePathsToNodeIds_async(client, paths, ids, pathSize,
                                                         translateCalled, NULL, &reqId);
#endif /* UA_ENABLE_METHODCALLS */
#endif
            /* How often UA_Client_run_iterate is called depends on the number of request sent */
            UA_Client_run_iterate(client, 0);
            UA_Client_run_iterate(client, 0);
        }
    }
    UA_Client_run_iterate(client, 0);

    /* Async disconnect kills unprocessed requests */
    // UA_Client_disconnect_async (client, &reqId); //can only be used when connected = true
    // UA_Client_run_iterate (client, &timedOut);
    UA_Client_disconnect(client);
    UA_Client_delete(client);

    return EXIT_SUCCESS;
}
