#include <Adafruit_CircuitPlayground.h>
#include "dis_check.h"
#include "alarm.h"
#include "power.h"
#define TINY_GSM_MODEM_ESP8266

#define SerialMon Serial
#define SerialAT Serial1

// Your io.adafruit.com credentials,
#define MQTT_USERNAME "###########"
#define MQTT_PASSWORD "###########"

const char MQTT_CLIENTID[] = MQTT_USERNAME __DATE__ __TIME__;

// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "###############";
const char wifiPass[] = "###############"";

// MQTT details
const char* broker = "io.adafruit.com";
const char* alarmTopic = MQTT_USERNAME "/feeds/alarm";
const char* alarmPlayTopic = MQTT_USERNAME "/feeds/alarmPlay";
const char* TvPowerTopic = MQTT_USERNAME "/feeds/TvPower";
const char* temperatureTopic = MQTT_USERNAME "/feeds/temperature";
const char* AcPowerTopic = MQTT_USERNAME "/feeds/AcPower";


//timeing
const long interval = 1000;
unsigned long previousMillis = 0;
long lastPublished = 0;

char temp[50];
String tempStr;

//distance_count
int dis_count = 0 ;
int flag = 0 ;

#include <TinyGsmClient.h>
#include <PubSubClient.h>

TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
PubSubClient mqtt(client);

uint32_t lastReconnectAttempt = 0;

char itoa_buf[12];

void setup() {
  CircuitPlayground.begin();
  //dis_check setup
  pinMode(A2, OUTPUT);
  pinMode(A1, INPUT);
  
  SerialMon.begin(115200);
  delay(1000);
  SerialAT.begin(115200);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  //modem.init();

  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);

  SerialMon.print(F("Setting SSID/password..."));
  if (!modem.networkConnect(wifiSSID, wifiPass)) {
    SerialMon.println(" fail");
    while(true);
  }
  SerialMon.println(" success");

  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    while(true);
  }
  SerialMon.println(" success");

  if (modem.isNetworkConnected()) {
    SerialMon.println("Network connected");
  }

  // MQTT Broker setup
  mqtt.setServer(broker, 1883);
  mqtt.setCallback(mqttCallback);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (!mqtt.connected()) {
      SerialMon.println("=== MQTT NOT CONNECTED ===");
      // Reconnect every 10 seconds
      uint32_t t = millis();
      if (t - lastReconnectAttempt > 10000L) {
        lastReconnectAttempt = t;
        if (mqttConnect()) {
          lastReconnectAttempt = 0;
          mqtt.publish(neopixelTopicStatus, "READY");
        }
      }
      delay(100);
      return;
    }
    mqtt.loop();
  }
  if (millis() - lastPublished > 10000) {
    checkTemp();
  }
  checkDistance();
  
}


void mqttCallback(char* topic, byte* payload, unsigned int len) {
  SerialMon.print("Message arrived [");
  SerialMon.print(topic);
  SerialMon.print("]: ");
  SerialMon.write(payload, len);
  SerialMon.println();

  // Only proceed if incoming message's topic matches
 
  if (String(topic) == alarmPlayTopic){
    play_alarm();
  }
  if (String(topic) == TvPowerTopic){
    power_off_TV();
  }
  if (String(topic) == AcPowerTopic){
    //power_off_AC();
  }
}

boolean mqttConnect() {
  SerialMon.print("Connecting to ");
  SerialMon.print(broker);

  // no password? no problem
  // boolean status = mqtt.connect(MQTT_CLIENTID);
  boolean status = mqtt.connect(MQTT_CLIENTID, MQTT_USERNAME, MQTT_PASSWORD);

  if (status == false) {
    SerialMon.println(" fail");
    return false;
  }
  SerialMon.println(" success");
  mqtt.subscribe(neopixelTopic);
  mqtt.subscribe(alarmPlayTopic);
  mqtt.subscribe(TvPowerTopic);
  mqtt.subscribe(AcPowerTopic);
  return mqtt.connected();
}

void checkDistance(){
  int dis_num = 0;
  dis_num = dis();
  if( NORMAL_DISTANCE - dis_num >= THRESHOLD_DISTANCE){
    dis_count++;
  }
  if(dis_count >5){
     dis_count = 0;
     flag++;
     mqtt.publish(alarmTopic, itoa(1, itoa_buf, 10));
     if(flag%2 == 0){
      flag = 0;
      mqtt.publish(alarmTopic, itoa(0, itoa_buf, 10));
    } 
  }
}
void checkTemp(){
  float ftemp = CircuitPlayground.temperature();
  tempStr = String(ftemp);
  tempStr.toCharArray(temp, tempStr.length() + 1);
  mqtt.publish(temperatureTopic, temp);
  lastPublished = millis();
}
