#include <Time.h>
#include <LiquidCrystal.h>
#include <Ethernet.h>
#include <SPI.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
#define TIME_MSG_LEN  11
#define TIME_HEADER  'T'
String location = "/~ictest00123/arduino.php?device_id=dev&password=2b336999049729f8b5a11d290356e24e62d29b7b HTTP/1.0";
byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0xF9, 0xEF}; // mac address of ethernet shield
int ledPin = 14;
int beepPin = 15;
int buttonPin = 8; // the number of the pushbutton pin
char serverName[] = "zafora.icte.uowm.gr"; // site
char inString[400]; // data table of parsing
int stringPos = 0; // count chars of parsing
int buttonState = 0; // variable for reading the pushbutton status
boolean startRead = false; // read data or not
boolean wra_or_mnm = 0; // print message or time
boolean LED = 0; // turn on or off LED
boolean BEEP = 0; // turn on or off BEEPER
String myTime = ""; // time sync. get value from site
String ID = ""; // message id
String USER = ""; // message id
String DATE = ""; // message id
String MSG = ""; // message id
EthernetClient client;
EthernetClient client2;
time_t read_start;
time_t read_end;
time_t refresh_start;
time_t refresh_end;
time_t aknow_start;
time_t aknow_end;
void setup(){
	Serial.begin(9600);
	Ethernet.begin(mac);
	lcd.begin(20, 4);
	pinMode(buttonPin, INPUT);
	pinMode(ledPin, OUTPUT);
	pinMode(beepPin, OUTPUT);
}
void beep(unsigned char delayms){
	digitalWrite(beepPin, HIGH);      // Almost any value can be used except 0 and 255
	delay(delayms);          // wait for a delayms ms
	digitalWrite(beepPin, 0);       // 0 turns it off
	delay(delayms);          // wait for a delayms ms
}  
void loop(){
	String pageValue = connectAndRead();
	client.stop();
	client.flush();
	lcd.clear();
	digitalWrite(ledPin, LOW);
	digitalWrite(beepPin, LOW);
	if(wra_or_mnm == 1){
		myTime = "T";
		for(int k = 1; k < stringPos; k++) myTime += inString[k];
		processSyncMessage();
		refresh_start = millis();
		refresh_end = refresh_start + 15000;
		while(refresh_start <= refresh_end){
			refresh_start = millis();
			lcd.setCursor(5, 1);
			digitaldateDisplay();
			lcd.setCursor(6, 2);
			digitalClockDisplay();
			delay(1000);
		}
	}
	else if(wra_or_mnm == 0){
		refresh_start = millis();
			for(int c=0;c<=15;c++){
				if(MSG.length()<=(40+(40*c))) {
					refresh_end =  ((1000*2*c) +  millis());
				}
			}
		while((buttonState == LOW) && (refresh_start < refresh_end)) {
			if(LED == 1)	digitalWrite(ledPin, HIGH);
			lcd.clear();
			lcd.setCursor(0, 0);
			user_print();
			lcd.setCursor(0, 1);
			lcd.print(DATE);
			msg_print();
			delay(500);
			lcd.clear();
			lcd.setCursor(0, 0);
			lcd.print("Aknowledge... ");
			digitalWrite(ledPin, LOW);
			digitalWrite(beepPin, LOW);
			aknow_start = millis();
			aknow_end = aknow_start + 4000;
			while((aknow_start<=aknow_end) && (buttonState == LOW)){
				if(aknow_end-aknow_start==4000){
					lcd.setCursor(13, 0);
					lcd.print("4");
				}
				else if(aknow_end-aknow_start==3000){
					lcd.setCursor(13, 0);
					lcd.print("3");
				}
				else if(aknow_end-aknow_start==2000){
					lcd.setCursor(13, 0);
					lcd.print("2");
				}
				else if(aknow_end-aknow_start==1000){
					lcd.setCursor(13, 0);
					lcd.print("1");
				}
				buttonState = digitalRead(buttonPin);
				aknow_start = millis();
			}
			refresh_start = millis();
		}
		lcd.clear();
		if (buttonState == HIGH){
			if (client2.connect(serverName,80)){
				client2.print("GET /~ictest00123/arduino.php?device_id=dev&password=2b336999049729f8b5a11d290356e24e62d29b7b&message_id=");
				client2.println(ID);
				client2.println(" HTTP/1.0");
                client2.println();
				lcd.clear();
				lcd.setCursor(0, 0);
				lcd.print("Message read ");
				lcd.setCursor(0, 1);
				lcd.print("succesfully! ");
                delay(2000);
                client2.stop();
			}
			else{
				lcd.clear();
				lcd.setCursor(0, 0);
				lcd.print("Aknowledge failed!");
                delay(2000);
			}
			buttonState = 0;
		}
		wra_or_mnm = 0;
		LED = 0;
		BEEP = 0;
		ID = "";
		USER = "";
		DATE = "";
		MSG = "";
	}
}
String connectAndRead(){
	if (client.connect(serverName, 80)) {
		client.print("GET ");
		client.println(location);
		client.println();
		lcd.clear();
		lcd.setCursor(0,0);
		lcd.print("connecting... ");
		delay(1000);
		return readPage();
	}
	else{
		software_Reset();
	}
}
void software_Reset() {
	asm volatile ("  jmp 0");
}
String readPage(){
	stringPos = 0;
	wra_or_mnm = 0;
	BEEP = 0;
	LED = 0;
	ID = "";
	USER = "";
	DATE = "";
	MSG = "";
	int start_id = 0;
	int start_user = 0;
	int start_date = 0;
	memset( &inString, 0, 400 );
	while(true){
		if (client.available()) {
			char c = client.read();
			if (c == '{' ) {
				startRead = true;
			}
			else if(startRead){
				if(c != '}'){
					inString[stringPos] = c;
					if(c == '*' && stringPos == 0) 					wra_or_mnm	= 1;
					if(c == '#' && inString[stringPos - 1] =='1') 	BEEP		= 1;
					if(c == '$' && inString[stringPos - 1] =='1') 	LED			= 1;
					
					if(c == '%')	start_user	= stringPos + 1;
					if(c == '^')	start_date	= stringPos + 1;
					if(c == '&')	start_id	= stringPos + 1;
					stringPos ++;
				}
				else{
					startRead = false;
					if(wra_or_mnm == 0){
						for(int i = start_id;	i < stringPos;	i++) ID		+= inString[i];
						for(int j = 5; 			j < start_user-1; j++) USER	+= inString[j];
						for(int k = start_user; k < start_date-1; k++) DATE	+= inString[k];
						for(int l = start_date; l < start_id-1; l++) MSG	+= inString[l];
					}
					client.stop();
					client.flush();
					return inString;
				}
			}
		}
	}
}
void digitalClockDisplay(){
	int wra;
	if((hour()+3) == 24) wra = 0;
	else if((hour()+3) == 25) wra = 1;
	else if((hour()+3) == 26) wra = 2;
	else wra = hour()+3;
	if((wra)<=9) lcd.print("0");
	lcd.print(wra);
	lcd.print(":");
	if(minute()<=9) lcd.print("0");
	lcd.print(minute());
	lcd.print(":");
	if(second()<=9) lcd.print("0");
	lcd.print(second());
}
void digitaldateDisplay(){
	int mera;
	int mhna;
	int xrono;
	if((hour()+3) >= 24){
		mera = day() + 1;
		if (month() == 1 || month() == 3 || month() == 5 || month() == 7 || month() == 8 || month() == 10 || month() == 12){
			if (mera==32){
				mera = 1;
				mhna = month() + 1;
				if(mhna == 13){ mhna = 1; xrono = year() + 1; }
				else xrono = year();
			}
			else{ mhna = month(); xrono = year(); }
		}
		else if (month() == 4 || month() == 6 || month() == 9 || month() == 11){
			if (mera==31){ mera = 1; mhna = month() + 1; xrono = year(); }
			else{ mhna = month(); xrono = year(); }
		}
		else if (month() == 2){
			if(year()%4==0){
				if (mera==30){ mera = 1; mhna = month() + 1; xrono = year(); }
				else{ mhna = month(); xrono = year(); }
			}
			else{
				if (mera==29){ mera = 1; mhna = month() + 1; xrono = year(); }
				else{ mhna = month(); xrono = year();}
			}
		}
	}
	else{mera = day(); mhna = month(); xrono = year();}
	if(mera<=9) lcd.print("0");
	lcd.print(mera);
	lcd.print("-");
	if(mhna<=9) lcd.print("0");
	lcd.print(mhna);
	lcd.print("-");
	lcd.print(xrono);
}
void processSyncMessage(){
	char c = myTime[0];
	if(c == TIME_HEADER){
		time_t pctime = 0;
		for(int i=0; i < TIME_MSG_LEN -1; i++){
			c = myTime[i+1];
			if( c >= '0' && c <= '9'){
				pctime = (10 * pctime) + (c - '0');
			}
		}
		setTime(pctime);
	}
}
void user_print(){
	int count = USER.length();
	if(count==21){
		USER.replace(" ", "");
		lcd.print(USER);
	}
	else if(count<=20){
		lcd.print(USER);
	}
	else{
		USER.replace(" ", "");
		for(int i=0; i<20; i++){
			lcd.print(USER[i]);
		}
	}
}
void msg_print(){
	if(BEEP == 1){
		beep(50);
		beep(50);
		beep(50);
		beep(50);
		beep(50);
	}
	int i = 0;
	int msg_len = MSG.length();
	while(i<msg_len){
		lcd.setCursor(0, 2);
		lcd.print("                    ");
		lcd.setCursor(0,3);
		lcd.print("                    ");
		lcd.setCursor(0, 2);
		while(MSG[i]!='|' && i<msg_len){
			lcd.print(MSG[i]);
			i++;
		}
		i++;
		lcd.setCursor(0,3);
		while(MSG[i]!='|' && i<msg_len){
			lcd.print(MSG[i]);
			i++;
		}
		i++;
		read_start = millis();
		read_end = read_start + 4000;
		while(read_start<=read_end){
			read_start = millis();
		}
	}
}