/*

Done Features:

- Initiate General Structure
- Add WiFi Support
- Add MQTT Support both for Subscribing and Publishing
- Add JSON support to handle MQTT messaging
- Add File Handling
- Add Melody Class with functions to Play/Pause/Stop etc.
- Add Main BellEngine
- Add custom Relay Timings (saved on-board)
- Add RTC support
- Add Timekeeper class, with functions to track time and call schedules
- Add OTA Update Functionality
- Add global logger with Mode Selection (None, Error, Warning, Info, Debug)
- Add Captive Portal / WiFi HotSpot
- Add NTP Time Sync

ToDo Features:

- Add reset to Factory Defaults button
- Add manual Sync-Time (for No-Connectivity Setups)
- Add the ability to report the list of melodies
- Add the ability to report a month's ScheduleEntry
- Add the ability to report the free space in SPIFFS.
- Add Bluetooth support
- Add WiFi Direct AP Support
- Add PCB Temperature Sensor
- Counters and Statistics:
	- Counter for each bell (counts total times the bell ringed)
	- Counter per bell, beats/minute for reliability and thermal protection. Warranty Void scenario.
	- Counter per playback, to figure out which melody is the most played.
	- Counter of items per Scheduler


*/

#include "logging.hpp"

#include <SD.h>
#include <FS.h>
#include <ETH.h>
#include <SPI.h>
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>
#include <AsyncMqttClient.h>
#include <ArduinoJson.h>
#include <string>
#include <Wire.h>
#include <Adafruit_PCF8574.h>
#include "RTClib.h"
#include <WebServer.h>
#include <ESPAsyncWebServer.h>
#include <WiFiManager.h>


// Hardware Constructors:
Adafruit_PCF8574 relays;
RTC_DS1307 rtc;

// SD Card Chip Select:
#define SD_CS 5

// Include Classes
#include "classes.hpp"

// Class Constructors
AsyncMqttClient mqttClient;
Player player;
std::vector<uint16_t> melody_steps; // holds the steps of the melody. Should move into bell Engine.
AsyncWebServer server(80);

AsyncWebSocket ws("/ws");

#include "config.h"
#include "ota.hpp"
#include "functions.hpp"
#include "MQTT_Message_Handling.hpp"
#include "MQTT_WiFi_Utilities.hpp"
#include "PlaybackControls.hpp"
#include "bellEngine.hpp"

TaskHandle_t bellEngineHandle = NULL;
TimerHandle_t schedulerTimer;



void setup()
{
  // Initialize Serial Communications & I2C Bus (for debugging)
	Serial.begin(115200);
	Wire.begin(4,15);
	SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI);
  delay(50);

	// Initialize PCF8574 and Relays
	relays.begin(PCF8574_ADDR, &Wire);
	for (uint8_t p=0; p<6; p++){
		relays.pinMode(p, OUTPUT);
		relays.digitalWrite(p, HIGH);
	}


	// Initialize SD Card
 	if (!SD.begin(SD_CS)) {
    Serial.println("SD card not found. Using defaults.");
  } else {
    // do nothing
  }

  // Initialize RTC
  if (!rtc.begin()) {
  LOG_ERROR("Couldn't find RTC");
  while(true) delay(10);
  }

	// Initialize Networking and MQTT
	Network.onEvent(NetworkEvent);
	ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI);
	InitMqtt();
	WiFiManager wm;
	//wm.resetSettings();  // Only for Debugging.
	bool res;
	res = wm.autoConnect(ap_ssid.c_str(),ap_pass.c_str());
	if(!res) {
			LOG_ERROR("Failed to connect to WiFi");
	}
	else {
			LOG_INFO("Connected to WiFi");
	}

  delay(100);

	checkForUpdates(); // checks for updates online
	syncTimeWithNTP(); // syncs time from NTP Server

	delay(100);

	// WebSocket setup
  ws.onEvent(onWebSocketEvent);
  server.addHandler(&ws);
  // Start the server
  server.begin();

	// Tasks and Timers
  xTaskCreatePinnedToCore(bellEngine,"bellEngine", 8192, NULL, 1, &bellEngineHandle, 1);
  xTaskCreatePinnedToCore(durationTimer, "durationTimer", 8192, NULL, 2, NULL, 1);
	xTaskCreatePinnedToCore(relayControlTask, "Relay Control", 2048, NULL, 2, NULL, 1);

	loadRelayTimings();
}


void loop()
{

}
