#ifndef MEDI_BOT_H
#define	MEDI_BOT_H
////////////////////////////////////
// clock AND protoThreads configure!
// You MUST check this file!
#include <plib.h>
#include "config.h"
// threading library
#include <stdio.h>
#include <math.h>
#include "pt_cornell_1_2.h"


////////////////////////////////////
// graphics libraries
#include "tft_master.h"
#include "tft_gfx.h"

// DMA definitons
#define dmaChn 0
#define sine_table_size 64

#define TOTAL_NUMBER_OF_MEDS 16
// system 1 second interval tick
int sys_time_seconds;
// string buffer
char buffer[180];
volatile int rtccIntCount = 0;

struct pt pt_timer, pt_serial, pt_DMA_output, pt_input, pt_receive, pt_sound;

static char user_name[16];

typedef enum  { USER_NAME, CURRENT_TIME, MEDICINE_SCHEDULE, DRIVE, FOLLOW} bluetooth_state_t;
typedef enum { SUNDAY = 0, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY} days_t;

__inline__ void update_medicine(void);

__inline__ void marshal_medicine(void);

char med_day [16];
int med_hour, med_min, med_quantity;
char med_name[16];
char rc_drive [16];

typedef struct {
    days_t day;
    int hour;
    int minute;
    int quantity;
} med_t;

volatile med_t meds[TOTAL_NUMBER_OF_MEDS];
volatile int number_of_meds = 0;
int current_medicine = 0;


volatile bluetooth_state_t medibot_bluetooth;

static int i,k;
volatile unsigned char sine_table[sine_table_size];
static int F_OUT = 3000;
static int output_sound;
static int alarm_msg;

char int2bcd(int value) {
    char tens = (value / 10);
    char ones = (value % 10);

    return (tens << 4) | ones;
}

int bcd2int(char value) {
    int ones = (int)( value & 0x0f);
    int tens = (int) ((value >> 4) & 0x0f);

    return (tens * 10 + ones);
}

int med2int(med_t m) {
    return ((int) m.day << 9) + (m.hour << 5) + (m.minute);
}

int c, d;
med_t swap;

int sort_meds(void) {
  for (c = 0 ; c < ( number_of_meds - 1 ); c++)  {
    for (d = 0 ; d < number_of_meds - c - 1; d++)
    {
      if ( med2int(meds[d]) > med2int(meds[d+1])) /* For decreasing order use < */ {
        swap.day        = meds[d].day;
        swap.hour       = meds[d].hour;
        swap.minute     = meds[d].minute;
        swap.quantity   = meds[d].quantity;

        meds[d].day         = meds[d+1].day;
        meds[d].hour        = meds[d+1].hour;
        meds[d].minute      = meds[d+1].minute;
        meds[d].quantity    = meds[d+1].quantity;

        meds[d+1].day       = swap.day;
        meds[d+1].hour      = swap.hour;
        meds[d+1].minute    = swap.minute;
        meds[d+1].quantity  = swap.quantity;
      }
    }
  }
}

rtccTime time_check;
rtccDate date_check;

BOOL compare_med_to_rtcc_time(int c) {
    RtccGetTimeDate(&time_check, &date_check);

    if  ( ( bcd2int(date_check.wday) <= meds[c].day) && ( bcd2int(time_check.hour) <= meds[c].hour) && (bcd2int(time_check.min)  < meds[c].minute) ) {
        return TRUE;
    }

    return FALSE;
}

rtccDate current_rtcc_date;
rtccTime current_rtcc_time;

void set_first_medicine(void) {
    RtccGetTimeDate(&current_rtcc_time, &current_rtcc_date);
    for (c = 0; c < number_of_meds; c++) {
        if (compare_med_to_rtcc_time(c)) {
            current_medicine = c;
            current_rtcc_date.wday = int2bcd(meds[current_medicine].day);
            current_rtcc_time.hour = int2bcd(meds[c].hour);
            current_rtcc_time.min = int2bcd(meds[c].minute);
            RtccChimeDisable();							// don't want rollover
            RtccSetAlarmRptCount(0);					// one alarm will do
            RtccSetAlarmRpt(RTCC_RPT_WEEK);			// enable repeat rate, check the second field
            RtccSetAlarmTimeDate(current_rtcc_time.l, current_rtcc_date.l);		// set the alarm time
            RtccAlarmEnable();							// enable the alarm

            if(RtccGetAlarmEnable())	// check that the alarm is enabled
            {
                // enabling/disabling the RTCC alarm interrupts
                INTSetVectorPriority(INT_RTCC_VECTOR, INT_PRIORITY_LEVEL_4);			// set the RTCC priority in the INT controller
                INTSetVectorSubPriority(INT_RTCC_VECTOR, INT_SUB_PRIORITY_LEVEL_1);		// set the RTCC sub-priority in the INT controller
                INTClearFlag(INT_RTCC);
                INTEnable(INT_RTCC, INT_ENABLED);					// enable the RTCC event interrupts in the INT controller.
                INTClearFlag(INT_RTCC);

                rtccIntCount = 0;
            }

            INTClearFlag(INT_RTCC);
            break;
        }
    }
}

void set_next_medicine(void) {
    current_medicine = (current_medicine + 1) % number_of_meds;
    RtccGetTimeDate(&current_rtcc_time, &current_rtcc_date);
    current_rtcc_date.wday = int2bcd(meds[current_medicine].day);
    current_rtcc_time.hour = int2bcd(meds[current_medicine].hour);
    current_rtcc_time.min = int2bcd(meds[current_medicine].minute);
    RtccChimeDisable();							// don't want rollover
    RtccSetAlarmRptCount(0);					// one alarm will do
    RtccSetAlarmRpt(RTCC_RPT_WEEK);			// enable repeat rate, check the second field
    RtccSetAlarmTimeDate(current_rtcc_time.l, current_rtcc_date.l);		// set the alarm time
    RtccAlarmEnable();							// enable the alarm

}
#endif	/* MEDI_BOT */

