/*
 * File:   peripheral_comm.c
 * Author: Brandon Mitchell
 *
 * Created on April 27, 2015, 8:58 AM
 *
 * Peripheral to Hub Communication
 */

#include "version.h"

#ifndef HUB_RN4020

#include "peripheral_comm.h"
#include "btle.h"
#include "timer.h"
//#include "config.h"
#include <xc.h>
#include <string.h>
#include "stdio.h"

#ifdef _DEBUG
    #include "led.h"
#endif

////////////////////////////////////////////////////////////////////////////////
// CONSTANTS
#define SCAN_TIME_ms 3000
#define CONNECT_TIME_ms 200
//#define MAX_VALUE_STRING_LENGTH 21
#define MAX_VALUE_STRING_LENGTH 37
//#define MAX_COMMAND_STRING_LENGTH 60
#define MAX_COMMAND_STRING_LENGTH 76

////////////////////////////////////////////////////////////////////////////////
// Public Data

pList_t pList;

////////////////////////////////////////////////////////////////////////////////
// Local Function Declarations

exitCondition_t ReadAndParseForMacAddressAndType( void );


////////////////////////////////////////////////////////////////////////////////
// Interface Function Definitions

// Initializes Peripheral List as empty
void InitPeripheral( void ) {

    pList.highestIndex = -1;
    pList.valid = 0;
    int ii;
    for( ii = 0; ii < MAX_NUM_MAC_ADDRESS; ++ii) {
        pList.periph[ii].type = NONE;
    }
}

// Scans for peripherals, parses list for MAC addresses and peripheral types,
// and stops scan and returns.
exitCondition_t FindHub( void ) {

    //Scan for peripheral devices
    btleCommand_t scan;
    scan.commandString = "F\r\n";
    scan.delayTime_ms = SCAN_TIME_ms;
    scan.responseLength = 0;
    scan.responseString = "";

    SendRawBtleCommand( & scan );
    TimerDelay_ms( scan.delayTime_ms );

    exitCondition_t result = ReadAndParseForMacAddressAndType();

    HandleBtleCommand( STOP_SCAN );
    TimerDelay_ms( 500 );
    ClearRxFifo();

    return result;
}

// Attempt to connect to peripheral in the list at index "index".
exitCondition_t ConnectToHub( int index ) {

    // build connect command
    btleCommand_t connect;
    connect.delayTime_ms = CONNECT_TIME_ms;
    connect.responseLength = 0;
    connect.responseString = "";

    unsigned char command[20] = { 0 };
    strncpy( command, "E,0,", 4 );
    strncat( command, pList.periph[index].macAddress, MAC_ADDRESS_LENGTH );
    strncat( command, "\r\n", 2 );

    connect.commandString = command;

    // send connect command
    HandleRawBtleCommand( & connect );
    TimerDelay_ms( connect.delayTime_ms );
//    if( BTLE_CONNECTED ) {
//        return EXIT__SUCCESS;
//    } else {
//        HandleBtleCommand( STOP_CONNECTION );
//        TimerDelay_ms( 100 );
//        return EXIT__FAILURE;
//    }
    return EXIT__SUCCESS;
}

// Sends data to hub
void SendData( periphType_t type, unsigned int data1, unsigned int data2 ) {

    btleCommand_t private;
    unsigned char command[MAX_COMMAND_STRING_LENGTH] = { 0 };
    unsigned char value[MAX_VALUE_STRING_LENGTH] = { 0 };
    unsigned char buffer[16] = { 0 };

    switch( type ) {
        case HUB:

            // Strings longer than 16 chars are truncated to 16 chars.
            // Strings restricted to alpha-numeric chars.
            //BtleStringToAsciiEncode( "HELLOWORLDHOWARE", value, MAX_VALUE_STRING_LENGTH );

            sprintf(&buffer[1], "%d", data1);    //Convert the SpO2 from decimal to string and then load it to a buffer starting from buffer[1].
            sprintf(&buffer[3], "%d", data2);    //Convert the Pulse_Rate from decimal to string and then load it to a buffer starting from buffer[3].
            buffer[0] = 'O';    // ASCII character in buffer[0] is used to identify from which remote/peripheral device the following data come.
                                // 'D'=PED, 'B'=BPM, 'O'=POX, T'=THR, 'G'=GLU, 'W'=WEI, 'H'=HRM.
            BtleStringToAsciiEncode( buffer, value, MAX_VALUE_STRING_LENGTH );
            
            strncpy( command, "SUW,12348765123487651234876512348765,", 37 );
            strncat( command, value, strlen( value ) );
            strncat( command, "\r\n", 2 );

            private.commandString = command;

            private.delayTime_ms   = 0;
            private.responseLength = 1;
            private.responseString = "";

            HandleRawBtleCommand( & private );
                        
            break;
        default:
            break;
    }
    TimerDelay_ms( 200 );
}

// removes peripheral MAC address and type from list at index "index"
exitCondition_t DeleteHubFromList( int index ) {

    if( index >= MAX_NUM_MAC_ADDRESS ) {
        return EXIT__FAILURE;
    }
    int ii;

    // move each peripheral up one index in the pList array
    for( ii = index; ii < MAX_NUM_MAC_ADDRESS - 2; ++ii ) {
        pList.periph[ii] = pList.periph[ii + 1];
    }

    // set the last peripheral to be empty
    pList.periph[MAX_NUM_MAC_ADDRESS - 1].type = NONE;
    --pList.highestIndex;
    if( pList.highestIndex < 0 ) {
        pList.valid = 0;
    }
    return EXIT__SUCCESS;
}


////////////////////////////////////////////////////////////////////////////////
// Local Function Definitions

// Reads the receiver FIFO, one line at a time.
// Parses each line for the MAC address and type, ignoring invalid data
// Adds MAC addresses and type to pList, up to PERIPHERAL_LIST_LENGTH peripherals
exitCondition_t ReadAndParseForMacAddressAndType( void ) {

    unsigned char * garbage, * name, * mac;
    int ii;

    ++pList.highestIndex;

    for( ii = 0; ii < MAX_NUM_MAC_ADDRESS && btleUart.numLinesReady > 0; ++ii) {
        // read a line from the FIFO
        if( ReadLineRxFifo( btleUart.rxResponse ) == EXIT__FAILURE ) {
            --pList.highestIndex;
            break;
        }

        // get MAC address
        mac = strtok( btleUart.rxResponse, ",");
        if( mac ) {
            memcpy( pList.periph[pList.highestIndex].macAddress, mac, MAC_ADDRESS_LENGTH + 1 );
        } else {
            continue;
        }

        //check for end of string
        if( !pList.periph[pList.highestIndex].macAddress ) {
            --pList.highestIndex;
            break;
        }

        //check for valid MAC address
        if( pList.periph[pList.highestIndex].macAddress[0] != '0') {
            continue; // Don't keep this macAddress
        }
        
        //check for duplicate MAC address
        int jj, duplicate = 0;
        for( jj = 0; jj < pList.highestIndex; ++jj ) {
            if( strcmp( pList.periph[jj].macAddress,
                        pList.periph[pList.highestIndex].macAddress ) == 0 ) {
                duplicate = 1;
            }
        }
        if( duplicate ) {
            continue; // Don't keep this macAddress
        }

        garbage = strtok( 0, "," ); // throw-away characters
        name = strtok( 0, ",");

        // check for valid device name
        if( strcmp( name, "MpgHub" ) == 0 ) {
            pList.periph[pList.highestIndex].type = HUB;
        } else {
            continue; // Don't keep this macAddress
        }
        pList.valid = 1;
        ++pList.highestIndex;
    }
    if( pList.valid ) {
        return EXIT__SUCCESS;
    } else {
        return EXIT__FAILURE;
    }
}

#endif
