/*
 * An example of a directly connected device which is capable of communicating
 * directly with Oracle IoT Cloud Service. This sample illustrates 
 * C code for sending data to the cloud service and does not fully explore the Client Library API.
 *
 * The sample uses the virtualization API. It presents a simple messenger.
 *
 * Device implements a device model. A device model is a set of related
 * attributes, actions, and message formats that can be represented in
 * a real device. For this example the "Hello World" device model is used.
 * This device model must be uploaded to the server before you can run this example.
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
/* include common public types */
#include "iotcs.h"
/* include iot cs device model APIs */
#include "iotcs_virtual_device.h"
/* include methods for device client*/
#include "iotcs_device.h"
 
/* Current device value */
static const char* device_current_value;
/* Device model handle */
static iotcs_device_model_handle device_model_handle = NULL;
/* Device handle */
static iotcs_virtual_device_handle device_handle = NULL;
 
/* print error message and terminate the program execution */
static void error(const char* message) {
    printf("Error occurred: %s\n", message);
    exit(EXIT_FAILURE);
}
 
int main(int argc, char** argv) {
    /* This is the URN of your device model. */
    const char* device_urns[] = {
        "urn:test:helloworld",
        NULL
    };
 
    iotcs_result rv;
 
    if (argc < 3) {
        error("Too few parameters.\n"
                "\nUsage:"
                "\n\tdirectly_connected_device.out path password"
                "\n\tpath is a path to trusted assets store."
                "\n\tpassword is a password for trusted assets store.");
    }
    const char* ts_path = argv[1];
    const char* ts_password = argv[2];
  
    /*
     * Initialize the library before any other calls.
     * Initiate all subsystems like ssl, TAM, request dispatcher,
     * async message dispatcher, etc., that are needed for correct library work.
     */
  
    if (iotcs_init(ts_path, ts_password) != IOTCS_RESULT_OK) {
        error("Initialization failed");
    }
 
    /*
     * Activate the device, if it's not already activated.
     * Always check if the device is activated before calling activate.
     * The device model URN is passed into the activate call to tell
     * the server the device model(s) that are supported by this
     * directly connected device.
     */
 
    if (!iotcs_is_activated()) {
        if (iotcs_activate(device_urns) != IOTCS_RESULT_OK) {
            error("Sending activation request failed");
        }
    }
 
    /* get device model handle */
    if (iotcs_get_device_model(device_urns[0], &device_model_handle) != IOTCS_RESULT_OK) {
        printf("iotcs_get_device_model method failed\n");
        return IOTCS_RESULT_FAIL;
    }
 
    /* get device handle */
    if (iotcs_create_virtual_device_handle(iotcs_get_endpoint_id(), device_model_handle, &device_handle) != IOTCS_RESULT_OK) {
        printf("iotcs_get_device_handle method failed\n");
        return IOTCS_RESULT_FAIL;
    }
 
    /* set device value */
    rv = iotcs_virtual_device_set_string(device_handle, "message", "Hello world!");
 
    if (rv != IOTCS_RESULT_OK) {
        printf("iotcs_virtual_device_set_string method failed\n");
        return IOTCS_RESULT_FAIL;
    }
 
    /* get current device value */
    if (iotcs_virtual_device_get_string(device_handle, "message", &device_current_value) != IOTCS_RESULT_OK) {
        printf("iotcs_virtual_device_get_string method failed\n");
        return IOTCS_RESULT_FAIL;
    }
 
    printf("Message is %s\n", device_current_value);
 
    /* free device handle */
    iotcs_free_virtual_device_handle(device_handle);
    /* free device model handle */
    iotcs_free_device_model(device_model_handle);
 
    /*
     * Calling finalization of the library ensures that communications channels are closed,
     * previously allocated temporary resources are released.
     */
    iotcs_finalize();
    printf("OK\n");
    return EXIT_SUCCESS;
}
