// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdlib.h>
#include <stdio.h>

#include "azure_c_shared_utility/platform.h"

#include "../../../certs/certs.h"

#include "prov_service_client/provisioning_service_client.h"

static bool g_use_trace = true;

#ifdef USE_OPENSSL
static bool g_use_certificate = true;
#else
static bool g_use_certificate = false;
#endif //USE_OPENSSL

int main()
{
    int result = 0;

    const char* connectionString = "[Connection String]";
    const char* registrationId = "[Registration Id]";
    const char* endorsementKey = "[Endorsement Key]";
    const char* deviceId = "[Device Id]";

    const char* tags = "{\"key\":\"value\"}";

    PROVISIONING_SERVICE_CLIENT_HANDLE prov_sc;
    ATTESTATION_MECHANISM_HANDLE am_handle;
    INDIVIDUAL_ENROLLMENT_HANDLE ie_handle;
    INITIAL_TWIN_HANDLE twin_handle;

    printf("Starting Individual Enrollment sample...\n");

    /* ---Create a Provisioning Service Client Handle--- */

    printf("Connecting to the Provisioning Service...\n");

    /*This function must be called before anything else so that sockets work*/
    platform_init();

    /* This creates a handle that will be used to represent a connection to the
    Device Provisioning Service indicated by the connection string given. */
    prov_sc = prov_sc_create_from_connection_string(connectionString);

    /* ---Optionally set connection options--- */
    if (g_use_trace)
    {
        prov_sc_set_trace(prov_sc, TRACING_STATUS_ON);
    }
    if (g_use_certificate)
    {
        prov_sc_set_certificate(prov_sc, certificates);
    }

    /* ---Create an Individual Enrollment structure--- */
    printf("Creating an Individual Enrollment structure...\n");

    am_handle = attestationMechanism_createWithTpm(endorsementKey, NULL);
    ie_handle = individualEnrollment_create(registrationId, am_handle);
    individualEnrollment_setDeviceId(ie_handle, deviceId); //optional - don't call if you don't need it

    /* ---Create the Individual Enrollment on the Provisioning Service--- */
    printf("Creating an Individual Enrollment on the Provisioning Service...\n");

    /*Note that after a successful create, the pointer of the given model
    is updated to contain new information generated by the Provisioning Service*/
    prov_sc_create_or_update_individual_enrollment(prov_sc, &ie_handle); //ie_handle is updated with info from the Provisioning Service (as if a get was performed)

    /* ---Retrieve an Individual Enrollment on the Provisioning Service--- */
    printf("Retrieving an Individual Enrollment from the Provisioning Service...\n");

    /*Note that in this context, doing a "get" call is a useless since the "create or update" call
    above already updated "ie_handle", and no changes have been made since. This is just to
    show you how a "get" would be performed */
    individualEnrollment_destroy(ie_handle);
    prov_sc_get_individual_enrollment(prov_sc, registrationId, &ie_handle);

    /* ---Update an Individual Enrollment on the Provisioning Service ---*/
    printf("Updated an Individual Enrollment structure\n");

    //in this example we'll add an initial twin state
    twin_handle = initialTwin_create(tags, NULL);
    individualEnrollment_setInitialTwin(ie_handle, twin_handle);

    /* This is the same call as we used for creation. However, because we already created the
    enrollment on the Provisioning Service, this call will now update the already existing one */
    prov_sc_create_or_update_individual_enrollment(prov_sc, &ie_handle);

    /* ---Delete an Individual Enrollment on the Provisioning Service--- */
    printf("Deleting an Individual Enrollment on the Provisioning Service...\n");

    prov_sc_delete_individual_enrollment(prov_sc, ie_handle);

    /* ---Clean up handles--- */
    individualEnrollment_destroy(ie_handle);
    prov_sc_destroy(prov_sc);
    platform_deinit();

    return result;
}
