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


#include "ip_connection.h"
#include "bricklet_rotary_poti.h"


/*
 * Prototypes
 */
static void cb_enumerate(const char *uid, const char *connected_uid,
        char position, uint8_t hardware_version[3],
        uint8_t firmware_version[3], uint16_t device_identifier,
        uint8_t enumeration_type, void *user_data);

static void cb_connect(uint8_t connect_reason, void *user_data);
static void cb_disconnect(uint8_t connect_reason, void *user_data);

static void show_info(void);
static void build_up_tf(void);
static void tear_down_tf(void);

static void application(void);

int main(int argc, char **argv)
{
    show_info();
    build_up_tf();
    application();
    tear_down_tf();
    return (EXIT_SUCCESS);
}

static void show_info()
{
    printf("Example Program: %s\n", __FILE__);
    printf("Hardware recognition: Dynamically detecting Rotary Bricklet\n"
            "                      USB disconnect and connect triggers callback!\n");
    printf("Application logic ..: N/A (no application)\n");
    printf("Source files .......: Just one (Monolithic).\n\n");
    printf("Press return to start ... ");
    getchar();
    printf("\n");
}

/*
 * Tinkerforge
 */
#define HOST "localhost"
#define PORT 4223


static IPConnection ipcon;

static RotaryPoti rp;
static int rotary_poti_is_valid;
static char rotary_poti_uid[8];

static void build_up_tf(void)
{
    rotary_poti_is_valid = 0;

    /* Create IP connection */
    ipcon_create(&ipcon);

    /* Connect to brickd */
    if (ipcon_connect(&ipcon, HOST, PORT) < 0)
    {
        fprintf(stderr, "Error: Could not connect to brickd. Exit.\n");
        exit(EXIT_FAILURE);
    }
    /* Register enumeration callback to "cb_enumerate" */
    ipcon_register_callback(&ipcon,
            IPCON_CALLBACK_ENUMERATE,
            (void *) cb_enumerate,
            NULL);

    ipcon_register_callback(&ipcon, IPCON_CALLBACK_CONNECTED, (void *) cb_connect, NULL);

    ipcon_register_callback(&ipcon, IPCON_CALLBACK_DISCONNECTED, (void *) cb_disconnect, NULL);
}

static void cb_connect(uint8_t connect_reason, void *user_data)
{
    printf("Connected to demon. Enumeration requested.\n");
    ipcon_enumerate(&ipcon);
}

static void cb_disconnect(uint8_t connect_reason, void *user_data)
{
    printf("Disconnected from demon.\n");
}

static void cb_enumerate(const char *uid, const char *connected_uid,
        char position, uint8_t hardware_version[3],
        uint8_t firmware_version[3], uint16_t device_identifier,
        uint8_t enumeration_type, void *user_data)
{
    (void) user_data;

    if (enumeration_type == IPCON_ENUMERATION_TYPE_DISCONNECTED)
    {
        if (rotary_poti_is_valid)
        {
            if (!strcmp(uid, rotary_poti_uid))
            {
                rotary_poti_is_valid = 0;
                rotary_poti_destroy(&rp);
                printf(" %s %s disconnected.\n", ROTARY_POTI_DEVICE_DISPLAY_NAME, uid);
            }
        }
    }
    else
    {
        if (device_identifier == ROTARY_POTI_DEVICE_IDENTIFIER)
        {
            printf(" %s %s available.\n", ROTARY_POTI_DEVICE_DISPLAY_NAME, uid);
            rotary_poti_is_valid = 1;
            rotary_poti_create(&rp, uid, &ipcon);
            strcpy(rotary_poti_uid, uid);
        }
    }
}

static void application(void)
{
    int16_t position;
    printf("Example code: read poti repeatedly ...\n ");

    while (1)
    {
        while (!rotary_poti_is_valid)
        {
            printf("Waiting for Rotary Poti Bricklet! ... \n");
            sleep(1);
        }
        if (rotary_poti_get_position(&rp, &position) < 0)
        {
            fprintf(stderr, "Error: Could not get position from bricklet. Exit.\n");
            exit(EXIT_FAILURE);
        }
        printf("Position: %hd\n", position);
    }

    printf("Press key to exit ...\n\n");
    getchar();

}

static void tear_down_tf(void)
{
    ipcon_destroy(&ipcon);
}
