//
//
// PlantModel
//
//

#include "ProjGlobals.h"
#include "PlantModel.h"
#include "WiFiStateHandler.h"
#include "Utility.h"


PlantData_T plant;			/// This keeps track of everything relevant to this system


String OnOffText(bool isOn) {
	if (isOn)
		return String("On");
	else
		return String("Off");
}

String DrumStateText(DrumState_E state) {
	switch (state) {
		case DrumIsOpen:
			return String("Open");
		case DrumIsClosed:
			return String("Closed");
		case DrumIsMoving:
			return String("Moving");
		default:
			return String("Error");
	}
}

String DrumMotorText(DrumMotor_E state) {
	switch (state) {
		case DrumOff:
			return String("Stopped");
		case DrumCW:
			return String("CW Rotation");
		case DrumCCW:
			return String("CCW Rotation");
		default:
			return String("Error");
	}
}

String DrumOpenText(bool isOpen) {
	if (isOpen)
		return String("Open");
	else
		return String("not open");
}
String DrumClosedText(bool isClosed) {
	if (isClosed)
		return String("Closed");
	else
		return String("not closed");
}

String WaterInTankText(bool waterInTank) {
	if (waterInTank)
		return String("OK");
	else
		return String("Empty");
}

// { 
//    "id": "5c:cf:7f:c0:52:82", 
//    "name": "3-Way Switch",
//    "state": 0, 
//    "sense": 56,
//    "ip": "192.168.1.23", 
//    "rssi": "-63", 
//    "countdown": "3:45",
//    "uptime": "0:11:45",
//    "wifimode": "station"|"ap"
// }
//
void HandleGetState() {
  int day, hr, minute, sec;
  char _upTime[15]; // 0000.00:00:00\0 + 1 spare

  sec = millis() / 1000;
  minute = sec / 60;
  hr = minute / 60;
  day = hr / 24;
  if (day)
    snprintf(_upTime, sizeof(_upTime), "%dd %d:%02d:%02d", day, hr % 24, minute % 60, sec % 60);
  else if (hr)
    snprintf(_upTime, sizeof(_upTime), "%d:%02d:%02d", hr, minute % 60, sec % 60);
  else
    snprintf(_upTime, sizeof(_upTime), "%02d:%02d", minute % 60, sec % 60);

  String modeText = (WiFiStateGet() == WFC_JoinedAP) ? "Station" : "Access Point";
  String message = "{\n";
  message += "\t\"id\": \"" + GetMacString() + "\",\n";
  message += "\t\"name\": \"" + wifiConfig.getName() + "\",\n";
  message += "\t\"version\": \"" + AP_VERS + "\",\n";
  //message += "\t\"state\": " + String(CurrStatus) + ",\n";
  //message += "\t\"raw\": " + String(iRaw) + ",\n";
  //message += "\t\"sense\": " + String(iRawSum / AVG_RATIO) + ",\n";
  message += "\t\"ip\": \""
    + String(WiFi.localIP()[0]) 
    + "." + String(WiFi.localIP()[1])
    + "." + String(WiFi.localIP()[2])
    + "." + String(WiFi.localIP()[3])
    + "\",\n";
  message += "\t\"rssi\": \"" + String(WiFi.RSSI()) + "\",\n";
  message += "\t\"uptime\": \"" + String(_upTime) + "\",\n";
  message += "\t\"wifimode\": \"" + modeText + "\",\n";

  snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.SecondsToday/3660, (plant.SecondsToday/60)%60);
  message += "\t\"TimeOfDay\": \"" + String(_upTime) + "\",\n";
  message += "\t\"Fahrenheit\": \"" + String(plant.Fahrenheit) + "\",\n";
  
  message += "\t\"ChamberTemp_C\": \"" + String(plant.ChamberTemp_C) + "\",\n";
  message += "\t\"ChamberHumi\": \"" + String(plant.ChamberHumi) + " % \",\n";
  message += "\t\"SoilHeater\": \"" + OnOffText(plant.SoilHeater) + "\",\n";
  message += "\t\"SoilTemp_C\": \"" + String(plant.SoilTemp_C) + "\",\n";
  message += "\t\"AmbientTemp_C\": \"" + String(plant.AmbientTemp_C) + "\",\n";
  message += "\t\"DrumDoorIcon\": \"" + DrumStateText(plant.DrumDoorIcon) + "\",\n";
  message += "\t\"DrumOpenSensor\": \"" + DrumOpenText(plant.DrumOpenSensor) + "\",\n";
  message += "\t\"DrumClosedSensor\": \"" + DrumClosedText(plant.DrumClosedSensor) + "\",\n";
  message += "\t\"DrumMotorStatus\": \"" + DrumMotorText(plant.DrumMotorStatus) + "\",\n";  
  message += "\t\"DrumMotor_V\": \"" + String(plant.DrumMotor_V) + "\",\n";  
  message += "\t\"DrumMotor_I\": \"" + String(plant.DrumMotor_I) + "\",\n";
  
  snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.DrumMotorOn_sec/60, plant.DrumMotorOn_sec%60);
  message += "\t\"DrumMotorOn_sec\": \"" + String(_upTime) + "\",\n";
  message += "\t\"WaterInTank\": \"" + String(plant.WaterInTank) + "\",\n";
  message += "\t\"WaterMotor_V\": \"" + String(plant.WaterPumpStatus) + "\",\n";
  message += "\t\"SoilMoisture_X\": \"" + String(plant.SoilMoisture_X) + "\",\n";
  
  snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCyclePeriod_sec/60, plant.WaterCyclePeriod_sec%60);
  message += "\t\"WaterCyclePeriod_sec\": \"" + String(_upTime) + "\",\n";

  snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCycleOn_sec/60, plant.WaterCycleOn_sec%60);
  message += "\t\"WaterCycleOn_sec\": \"" + String(_upTime) + "\",\n";

  snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCycle_sec/60, plant.WaterCycle_sec%60);
  message += "\t\"waterCycle\": \"" + String(_upTime) + "\"\n";
  //message += "\t\"toggle\": " + String(!digitalRead(SW_TOGGLE)) + ",\n";
  //message += "\t\"reset\": " + String(!digitalRead(SW_RESET));
  message += "}\n";
  server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
  server.send(200, "application/json", message);
}




void simulation() {
	if (++plant.SecondsToday >= (24*3600)) {		// Seconds are advancing really fast for the simulation
		plant.SecondsToday -= (24 * 3600);
	}
	static int lastMinutesToday = -1;
	int hoursToday = plant.SecondsToday / 3600;
	int minutesToday = plant.SecondsToday / 60;
	// Simulate Ambient temp rising and falling
	if (lastMinutesToday != minutesToday) {
		lastMinutesToday = minutesToday;
		Serial.printf("%02u:%02u, Ambient %3.1f\n", hoursToday, minutesToday % 60, plant.AmbientTemp_C);
	
		if (hoursToday < 15) {
			// warming part of the day
			if (plant.AmbientTemp_C < 45.0) {
				plant.AmbientTemp_C += (float)(rand() % 10)/1000.0;
			}
		} else {
			// cooling part of the day
			if (plant.AmbientTemp_C > 10.0) {
				plant.AmbientTemp_C -= (float)(rand() % 10)/1000.0;
			}
		}
		if (plant.SoilTemp_C > 40.0) {
			plant.SoilHeater = false;
		} else if (plant.SoilTemp_C < 20.0) {
			plant.SoilHeater = true;
		}
		if (plant.SoilHeater) {
			if (plant.SoilTemp_C < 50.0) {
				plant.SoilTemp_C += (float)(rand() % 10)/1000.0;
			}
		} else {
			if (plant.SoilTemp_C < plant.ChamberTemp_C) {
				plant.SoilTemp_C += (float)(rand() % 10)/1000.0;
			} else {
				plant.SoilTemp_C -= (float)(rand() % 10)/1000.0;
			}
		}
		if (plant.DrumMotorStatus == DrumCW) {
			plant.DrumMotorOn_sec++;
		} else if (plant.DrumMotorStatus == DrumCCW) {
			plant.DrumMotorOn_sec++;
		} else {
			plant.DrumMotorOn_sec = 0;
		}
		if (plant.ChamberTemp_C > 50.0) {
			if (!plant.DrumOpenSensor) {
				plant.DrumMotorStatus = DrumCW;
				if (plant.DrumMotorOn_sec > 50) {
					plant.DrumOpenSensor = true;
					plant.DrumClosedSensor = false;
				}
			}
		} else if (plant.ChamberTemp_C < 40.0) {
			if (!plant.DrumClosedSensor) {
				plant.DrumMotorStatus = DrumCW;
				if (plant.DrumMotorOn_sec > 50) {
					plant.DrumOpenSensor = false;
					plant.DrumClosedSensor = true;
				}
			}
		}
		if (plant.DrumDoorIcon == DrumIsOpen) {
			if (plant.ChamberTemp_C > plant.AmbientTemp_C) {
				plant.ChamberTemp_C -= (float)(rand() % 10)/1000.0;
			} else if (plant.ChamberTemp_C < plant.AmbientTemp_C) {
				plant.ChamberTemp_C += (float)(rand() % 10)/1000.0;
			}
		} else {
			if (plant.ChamberTemp_C > plant.AmbientTemp_C) {
				plant.ChamberTemp_C -= (float)(rand() % 5)/1000.0;
			} else if (plant.ChamberTemp_C < plant.AmbientTemp_C) {
				plant.ChamberTemp_C += (float)(rand() % 20)/1000.0;
			}
		}
		plant.ChamberHumi = (float)(rand() % 73) + 25;
		if (++plant.WaterCycle_sec >= plant.WaterCyclePeriod_sec) {
			plant.WaterCycle_sec -= plant.WaterCyclePeriod_sec;
		}
		if (plant.WaterCycle_sec >= plant.WaterCycleOn_sec) {
			plant.WaterPumpStatus = false;
		}
		if (plant.SoilMoisture_X < 60.0 && plant.WaterCycle_sec < plant.WaterCycleOn_sec) {
			plant.WaterPumpStatus = true;
		}
		if (plant.WaterPumpStatus) {
			plant.SoilMoisture_X += (float)(rand() % 40)/100.0;
		} else {
			plant.SoilMoisture_X -= (float)(rand() % 5)/100.0;
		}
	}
}
