#ifndef MAIN_H_
#define MAIN_H_

#include <lcd.h>
#include <QEI.h>
#include <touch.h>
#include <sd_card.h>
#include <VS1063.h>
#include <I2C.h>

#include "stdint.h"
#include "stdbool.h"
#include "string.h"
#include "stdlib.h"
#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_qei.h"
#include "inc/hw_i2c.h"
#include "inc/hw_hibernate.h"
#include "inc/tm4c123gh6pge.h"
#include "driverlib/timer.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/qei.h"
#include "driverlib/pwm.h"
#include "driverlib/ssi.h"
#include "driverlib/i2c.h"
#include "driverlib/hibernate.h"
#include "driverlib/interrupt.h"
#include "driverlib/fpu.h"
#include "driverlib/rom.h"
#include "driverlib/systick.h"
#include "driverlib/rom_map.h"
#include "driverlib/ssi.h"
#include "fatfs/src/ff.h"
#include "fatfs/src/diskio.h"

unsigned long ulPeriod;
volatile uint32_t ui32Loop;
volatile uint32_t position;

// The following are data structures used by FatFs
static FATFS g_sFatFs;
static DIR g_sDirObject;
static FILINFO g_sFileInfo;
static FIL g_sFileObject;
// A structure that holds a mapping between an FRESULT numerical code, and a
// string representation.  FRESULT codes are returned from the FatFs FAT file
// system driver.
typedef struct
{
    FRESULT iFResult;
    char *pcResultStr;
}
tFResultString;
// A table that holds a mapping between the numerical FRESULT code and it's
// name as a string.  This is used for looking up error codes for printing to
// the console.
static tFResultString g_psFResultStrings[] =
{
    FRESULT_ENTRY(FR_OK),
    FRESULT_ENTRY(FR_DISK_ERR),
    FRESULT_ENTRY(FR_INT_ERR),
    FRESULT_ENTRY(FR_NOT_READY),
    FRESULT_ENTRY(FR_NO_FILE),
    FRESULT_ENTRY(FR_NO_PATH),
    FRESULT_ENTRY(FR_INVALID_NAME),
    FRESULT_ENTRY(FR_DENIED),
    FRESULT_ENTRY(FR_EXIST),
    FRESULT_ENTRY(FR_INVALID_OBJECT),
    FRESULT_ENTRY(FR_WRITE_PROTECTED),
    FRESULT_ENTRY(FR_INVALID_DRIVE),
    FRESULT_ENTRY(FR_NOT_ENABLED),
    FRESULT_ENTRY(FR_NO_FILESYSTEM),
    FRESULT_ENTRY(FR_MKFS_ABORTED),
    FRESULT_ENTRY(FR_TIMEOUT),
    FRESULT_ENTRY(FR_LOCKED),
    FRESULT_ENTRY(FR_NOT_ENOUGH_CORE),
    FRESULT_ENTRY(FR_TOO_MANY_OPEN_FILES),
    FRESULT_ENTRY(FR_INVALID_PARAMETER),
};

void init();
void switchTouchEvent();
void switchENCEvent();
void interruptCtrl();
void watchDog(bool set);
// Interrupt routines
void GPIO_C_Handler();
void GPIO_H_Handler();
void GPIO_G_Handler();
void Timer0A_Handler();
void Timer1A_Handler();

enum menu_layer {start,select,player,setup,info,eq,eq_bar};		// Contains all menus
enum touch {NO_EVENT,BUT_OFF,BUT_INFO,BUT_SETUP,BUT_PLAYER,BUT_BACK,BUT_ENTER,BUT_EQ,BUT_FF,BUT_FORWARD,BUT_REVERS,BUT_FR,BUT_STOP,BUT_PP};	// Contains all touchevents
enum event {no_event_flag,touch_flag,encoder_flag,timer0_flag,data_req_flag};			// All events
enum enc   {push0,push1,up0,up1,down0,down1,no_event};									// All encoder events
enum state {play, stop, pause, FF, FR};													// All player states
enum pic   {play_set,start_set,standard_set,eq_set,eq_bar_set};								// All graphics

// Structure of all neccessary infos of an MP3 file header
typedef struct
{
	char* file_name;
	char* artist;
	char* titel;
	char* album;
	char* genre;
}
song;

// Structure which contains all infos of an graphic for the display
typedef struct
{
	int x_pos;
	int y_pos;
	int color;
	int back_color;
	enum menu_layer layer;
	enum pic window;
}
graphic;

// Structure to store encoder events
struct qei
{
	int ENC0_Value;		// Absolute counter value
	int ENC0_Push;		// Value if button was pushed
	int ENC0_UP;		// Value of steps increased to the previous value
	int ENC0_DOWN;		// Value of steps decreased to the previous value
	int ENC0_MAX;		// Value of the step maximum
	int ENC1_Value;		// Absolute counter value
	int ENC1_Push;		// Value if button was pushed
	int ENC1_UP;		// Value of steps increased to the previous value
	int ENC1_DOWN;		// Value of steps decreased to the previous value
	int ENC1_MAX;		// Value of the step maximum
};

// Contains all error typs that may occure
typedef struct
{
	char* SD_error;
	char* VS_error;
	char* I2C_error;
	char* tim_error;
	char* err_error;
} err;

struct work
{
	enum menu_layer cur_menu;	// Actuell menulayer
	enum menu_layer loc_menu;	// Second variable for current menu
	enum menu_layer last_menu;	// Last menulayer

	enum touch touch_event;	// Contains the touched button
	enum enc   enc_event;	// Contains the encoder event
	enum event event_flag;	// Flag what causes an interrupt and should be served

	enum state  play_state;	// What should the VS1063 do
	int         file_pos;	// Current position in file
	song		song_data;

	err      	error;		// Hold the errors that occurs

	char* 	    cur_dir;		// Current working directory
	char* 	    dir_path;	// Fully path to current directory "/test/sampel/cur_dir" but without cur_dir
	char* 	    cur_file;	// Current working file
	char*	    file_path;	// Fully path to current file
	uint32_t    file_count;	// Stores the number of files in the working directory
	uint32_t    dir_count;	// Stores the number of directorys in the working directory
	int 		isDir;		// Signals that we are working in directory

	int		    sel_pointer; // Y_Pos of the current select pointer
	int 	    cur_volume;	// Actuell volume level
	int 	    eq_pointer;	// Pointer to the actuell selected eq_bar
};

struct info
{
	int 			brightness;			// Integer of the LCD brightness
	float 			bat_voltage;		// Integer ot the batterie voltage
	int 			bat_level;			// Integer of the leaving batterie power
	float 			free_space;		//
	char* 			version;
	signed int 		EQ1_lvl;
	signed int 		EQ2_lvl;
	signed int 		EQ3_lvl;
	signed int 		EQ4_lvl;
	signed int		EQ5_lvl;
};

char** dir_list;			// Contains a list of all directorys in the current directory
char** file_list;			// Contains a list of all files in the current directory

#endif
