// Joshua umholtz-Judson Web server ardiono code
// This program will he used to host my personal webpage
// Version 1.3.6
// First initialize the variables needed
#include Ethernet.h
#include SPI.h
#include SD.h
#include Wire.h
#include LiquidCrystal_I2C.h
#include WatchDog.h
//Include Local Files
#include "Sensors.h"
#include "WebProto.h"

LiquidCrystal_I2C LCD(0x27, 16, 2);  //Setup LCD display

#define ReqBuff 20

// Network related initialization 
//Note: It is much more consistent to use the DNS function of the router.
// I have set the router to use a static IP for this devices MAC address
byte MAC[] = { 0xA8, 0x61, 0x0A, 0xAE, 0xF4, 0x1D };
//IPAddress IP(192, 168, 50, 140);
//byte subnet[] = { 255, 255, 255, 0 };
//byte gateway[] = { 192, 168, 50, 1 };
EthernetServer serv(80); // Externally 17248
//File tsFile;  //To Send File
char httpReq[ReqBuff] = { 0 };
char reqDex = 0;

//Pin inputs here
int  linBrad = A14;    //Line in for Before radiator temp
int  linArad = A15;    //Line in for After radiator temp 
int FlowIn = 3;  //Flow sensor pin must be 2,3,18,19 for interupts on Mega;

//variables for temperatures
float TBRad[] = { 0.0, 0.0, 0.0, 0.0, 0.0};
float TARad[] = { 0.0, 0.0, 0.0, 0.0, 0.0};

//Variables for flow sensor
float flow;
bool chng = 0;
bool comp = 0;
unsigned long timeyWimey[] = { 0, 0 };

// Buzzer Alarm Pin for if temps are hot sound alarm (Annoying kept off)
//int Buzz = 46;


void (*resetFunc)(void) = 0;  // reset to prevent freezes
//Setup the program here, initialize the components
void setup() {

  //Disable Ethernet pin due to conflict because I am using SD
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  
  uint8_t macd;
  //pinMode(Buzz, OUTPUT);

  //Currently not using serial in final product to increase speed, Still used at startup
  //Higher USB Baud rate seems to help potential communication issues
  Serial.begin(115200);
  //wait for serial a bit
  delay(10);

  //Initialize SD card
  if (SD.begin(4)) {
    Serial.println("SD Card Initialized");
  } else {
    Serial.println("SD Card FAILED INIT!");
    delay(777);  //Wait fo user to potentially reset.
    resetFunc();
  }
  //Test SD card for known files
  if(SD.exists("Main136.htm")){
    Serial.println("Main Page Good");
  }
  else{
    Serial.println("!Could Not Find Main!");
  }
  if(SD.exists("BackEnd1.htm")){
    Serial.println("BackEnd Page Good");
  }
  else{
    Serial.println("!Could Not Find BackEnd!");
  }
  if(SD.exists("WebCode1.htm")){
    Serial.println("WebCode Page Good");
  }
  else{
    Serial.println("!Could Not Find WebCode!");
  }

  Sensors s;

  //Network Start
  //Start ethernet stuff and report to serial
  Ethernet.init();
  Ethernet.begin(MAC);
  Serial.println("Ethernet Starting Up");

  //Check for hardware and wait for it if need be
  while (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("No Ethernet hardware found!!");
    delay(2000);
  };
    Serial.println("Hardware Detected move along");

  //Check for link status and wait if need be
  while (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("No link status!!");
    delay(2000);
  };
  Serial.println("Link on Roll out!");

  serv.begin();
  delay(10);
  Serial.print("Server is online! IP: ");
  Serial.println(Ethernet.localIP());
  delay(10);
  Serial.print("DNS Server IP: ");
  Serial.println(Ethernet.dnsServerIP());
  delay(10);
  Serial.print("Gateway IP: ");
  Serial.println(Ethernet.gatewayIP());
  delay(10);
  //Serial.print("Server MAC: ");
  //Ethernet.MACAddress(macd);
  //delay(10);
  //Serial.println(macd);

  //Set up bluetooth Pins and Baud Rate, Default 9600
  Serial2.begin(9600);
  delay(5);
  Serial.println("Bluetooth ON");

  //Initialize LCD
  LCD.init();
  LCD.backlight();
  LCD.print("Bef. ");
  LCD.setCursor(0, 1);
  LCD.print("Aft. ");
  LCD.setCursor(12, 0);
  LCD.print("RPM");

  //Do interupts Last so they dont cause potential setup issues
  //Flow sensor input interupt here 
  pinMode(FlowIn, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(FlowIn), flItr, FALLING);

}  //END OF SETUP

void loop() {
  //Get updated sensor data first
  Sensors s;
  s.UpBRadTemps(linBrad);
  s.UpARadTemps(linArad);
  comp = s.UpFlow(chng, comp);
  
  //Here is where we handle the website stuff
  //check for client availability
  EthernetClient kly = serv.available();
  if (kly) {
    //Serial.println("New client detected");
    bool httpEnd = true;
    while (kly.connected()) {
      if (kly.available()) {
        char N = kly.read();
        if (reqDex  (ReqBuff - 1)) {
          httpReq[reqDex] = N;
          reqDex++;
        }
        //Can we write yet? If so go ahead and send the webpage
        if (N == '\n' && httpEnd) {
          //Serial.println(httpReq); // Print out what the received request was
          WebProto wp;
          int i = 0;
          // Check what is requested and make a call to send selected web object
          // ***** Sending of webpages or text starts here  *****
          
          //Main Page Requested
          if (strstr(httpReq, "GET / ") || (strstr(httpReq, "GET /Main136.htm"))) {
            wp.wriWebPages(kly, (++i));             
          }

          //Write Web page for HTML Code
          else if ((strstr(httpReq, "GET /WebCode1.htm"))) {
            wp.wriWebPages(kly, (i+2));
          }

          //Write HTML code file to web page
          else if ((strstr(httpReq, "GET /WebFil.txt"))) {
            wp.wriWebPages(kly, (i+3));
          }

          // Send the Arduino Code Webpage here
          else if ((strstr(httpReq, "GET /BackEnd1.htm"))) {
            wp.wriWebPages(kly, (i+4));
          }
          //Write Ardiono Code File
          else if ((strstr(httpReq, "GET /BeManFl.txt"))) {
            wp.wriWebPages(kly, (i+5));
          }
          //send the CSS file here
          else if (strstr(httpReq, "GET /w3.css")) {
            wp.wriWebPages(kly, (i+6));
          } 
          //send the Web Functions file here
          else if (strstr(httpReq, "GET /WebFunFl.txt")) {
            wp.wriWebPages(kly, (i+7));
          } 
          //send the Sensor Functions file here
          else if (strstr(httpReq, "GET /SensFl.txt")) {
            wp.wriWebPages(kly, (i+8));
          } 
          // Send Projects related webpages here
          else if (strstr(httpReq, "GET /PrjWp1.htm")) {
            wp.wriWebPages(kly, (i+9));
          } 
          // ***** Here is where we switch from web pages or text to images *****
          // Send the Icon here or placeholder image
          else if ((strstr(httpReq, "GET /CYBPLACE.jpg")) || (strstr(httpReq, "GET /favicon.ico"))) {
            wp.wriImgs(kly, ++i);
          } 
          // Send the Self image file here
          else if (strstr(httpReq, "GET /SELFPIC.jpg")) {
            wp.wriImgs(kly, (i+2));
          }  
          // ***** Here we switch to sending Sensor Data below here *****
          //Send the temperature going into the radiator
          else if (strstr(httpReq, "GET /fint.txt")) {
            wp.wriSens(kly, ++i);
          } 
          //Send the tmeperature out from the radiator
          else if (strstr(httpReq, "GET /fout.txt")) {
            wp.wriSens(kly, (i+2));
          } 
          //Send the flow speed here
          else if (strstr(httpReq, "GET /flow.txt")) {
            wp.wriSens(kly, (i+3));
          } 
          else {// Unknown Request or bad request
            kly.println("HTTP/1.1 404 NOT FOUND");
            kly.println("");
            //Serial.println("Err 404");
          }
          //Reset buffers
          reqDex = 0;
          clStr(httpReq, ReqBuff);
          break;  //Break out of the while statement, were done
        }; //End of file sending

        //Check is its the end of the request
        if (N == '\n') httpEnd = true;
        else if (N != '\r') httpEnd = false;
      };  //End Available
    };  //End of Cennected stage
    //Pause and close connection
    delay(1);
    kly.stop();
    //Serial.println(httpReq);
    //Serial.println("Client closed");
  }//End of Client

  //Print the current values to the connected display module
  LCD.setCursor(5, 0);
  LCD.print(TBRad[0]);
  LCD.setCursor(5, 1);
  LCD.print(TARad[0]);
  LCD.setCursor(12, 1);
  LCD.print(flow);

  //reset every ~hour to keep glitches away
  if (5001000  millis()) resetFunc();

  //Serial.println("Ended Main Loop"); // For testing for hangups
}//End of main loop

//Clear the character string
void clStr(char *str, char length) { 
  for (int p = 0; p  length; p++) str[p] = 0;
};

// Update the array with newest rotation time
void flItr() {  
  //set next flow time in milliseconds
  timeyWimey[chng] = millis();
  //Serial.println("I"); //  !! Dont do this on an interupt it causes issues REAL QUICK!!
  //change chng to next number
  chng = !chng;
  return;
};