//ライブラリをインストールします
#include <M5Core2.h>          //M5Core2のライブラリをインクルード
#include <BluetoothSerial.h>  //ブルートゥースのライブラリをインクルード
#include <FS.h>               //内部データーベースのライブラリをインクルード
#include <SPIFFS.h>           //SPIFFSライブラリをインクルード
#include <WiFi.h>     // WiFiライブラリをインクルード

#include "logo2.h"  //画像ファイルです

BluetoothSerial SerialBT;  //ブルートゥースに使うなにかです。よくわかっていません


//グローバル変数置き場
int setting_sequence = 1; //セッティングスクリプトのシーケンスを1に設定します


//最初の処理
void setup() {
  M5.begin();  //m5を使うためのもの
  SPIFFS.begin();//内部データを利用するための処理
  M5.Axp.ScreenBreath(100);                           // 画面の明るさを100
  M5.Lcd.setRotation(1);                              // 画面の向きをちょうせい
  M5.Lcd.fillScreen(WHITE);                           // 背景色
  M5.Lcd.setSwapBytes(false);                         // 色がおかしい場合に変更する
  M5.Lcd.startWrite();                                //画面表示開始
  M5.Lcd.pushImage(0, 0, imgWidth, imgHeight, logo);  //起動ロゴを表示
  Serial.println("起動しました");//起動時にシリアルに送信(開発用)
  delay(1000);  //少し待機
  M5.Lcd.endWrite();//描画を一度終了します
  Serial.println("WiFiコンフィグ探知");//内部メモリを確認しシリアルに送信(開発用)
  if (SPIFFS.exists("/wifi_credentials.txt")) {  //WiFIの設定が済まされているかどうか
    Serial.println("wifi_credentials.txtが存在します");//内部メモリを確認しシリアルに送信(開発用)
    setting_sequence = 0;  //WiFiの設定が存在する場合、settingを0に設定
  }//if文終了
  Serial.println("コンフィグ探知終了");//内部メモリを確認しシリアルに送信(開発用)
  if (setting_sequence == 1) {  //初回起動に動作させるもの
    M5.Lcd.pushImage(0, 0, imgWidth, imgHeight, QR);//設定用のQRコードを表示
    Serial.println("ロゴ表示完了");//ロゴ表示完了をシリアルに送信(開発用)
    M5.Lcd.endWrite();  //設定用のロゴを表示

    SerialBT.begin("BambooCompost");//ブルートゥースのデバイス名を定義しています
    Serial.println("ブルートゥースを開始しました");//ブルートゥース接続開始をシリアルに送信(開発用)
  }//if文終了
}//void setup終了


//メインのループです
void loop() {
  //初回設定用のコード
  if (setting_sequence == 1) {//設定進度1の時に実行(void BTSettingの部分を実行します)
    BTSetting()//ブルートゥースで初回コネクト
  }//if文終了
  if (setting_sequence == 2) {//設定進度2の時に実行
    receiveWiFiSettings();//WiFiのせってい(void receiveWiFiSettingsの部分を実行します)
  }//if文終了
  if (setting_sequence == 3) {//設定進度3の時に実行
    receiveWiFiSettings();
  }//if文終了
}//void loop終了


//ブルートゥースで最初のコネクトを行います
void BTSetting() {
  if (SerialBT.available()) {//初回ブルートゥースコネクトの処理
    String receivedData = SerialBT.readStringUntil('\n');//受け取ったデータの処理
    receivedData.trim();//受け取ったデータの処理
    if (receivedData.equals("connect")) { //接続先から送信された文字列が「connect」な場合に処理を実行します
      receivedData.trim();//受け取ったデータの処理
      char* macAddress = getMAC();//WiFiのMacアドレスを取得します(char* getMACを実行します)
      SerialBT.println(macAddress);//接続先の危機に自身のMacアドレスを送信します
      setting_sequence = 2;//設定進度を2に移行
      Serial.println("コネクト");//ブルートゥース接続をシリアルに送信(開発用)
    }//if文終了
  }//if文終了
}//void BTSetting終了


// WiFiの設定情報を受信
void receiveWiFiSettings() {
  String wifiSettings = SerialBT.readStringUntil('\n');//受け取ったデータの処理
  wifiSettings.trim();//受け取ったデータの処理

  // カンマで分割
  int separatorIndex = wifiSettings.indexOf(',');//WiFiのパスワードとSSID(WiFiの名前)を受信
  if (separatorIndex != -1) {//チェック
    String ssid = wifiSettings.substring(0, separatorIndex);//パスワードとSSIDを分割
    String password = wifiSettings.substring(separatorIndex + 1);//パスワードとSSIDを分割

    // SPIFFSにWiFiの設定情報を保存
    saveWiFiCredentials(ssid, password);//内部データーベースに設定内容を保存します(void saveWiFiCredentialsの部分を実行)
  }//if文終了
}//void receiveWiFiSettings文終了


//内部データにWiFiのデータを書き込む
void saveWiFiCredentials(const String& ssid, const String& password) {// SPIFFSにファイルを書き込み
  File file = SPIFFS.open("/wifi_credentials.txt", "w");//wifi_credentials.txtというテキストに書き込みます
  if (file) {// ファイルチェック
    file.println("SSID=" + ssid);// SPIFFSにファイルを書き込み
    file.println("Password=" + password);// SPIFFSにファイルを書き込み
    file.close();//ファイルを閉じる
    Serial.println("WiFi credentials saved successfully.");//書き込めたことをシリアルに送信(開発用)
    setting_sequence = 3;//設定進度を3に移行
  } else {//if文の「または~」
    Serial.println("Error saving WiFi credentials to SPIFFS");//エラーが出たときにシリアルに送信(開発用)
  }//if文終了
}//void saveWiFiCredentials終了


//WiFiのMacアドレスを取得します
char* getMAC() {
  uint8_t baseMac[6];//WiFiのMacアドレスを取得します
  esp_read_mac(baseMac, ESP_MAC_WIFI_STA);//WiFiのMacアドレスを取得します
  static char baseMacChr[18] = {0};  // 静的な変数として宣言
  sprintf(baseMacChr, "%02X:%02X:%02X:%02X:%02X:%02X", baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);//WiFiのMacアドレスを取得します
  Serial.println(baseMacChr);//WiFiのMacアドレスをシリアルに送信(開発用)
  return baseMacChr;  // baseMacChr のアドレスを返す
}//char* getMAC終了