/***********************************************************************************
 * 
 */

//Define Firebase Data object
FirebaseData fbdo;

FirebaseAuth auth;
FirebaseConfig config;


void Firebase_init() {
  //
  // Set up and connection to Google Firebase used as the backend of the application
  //

  Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION);

  // If no static parameters defined, read them from EEPROM (assumed initialized)
  if (!STATIC_PARAMETERS) {
    API_KEY = Eeprom_read(stored_api_key_addr, stored_api_key_len);
    USER_EMAIL = Eeprom_read(stored_user_email_addr, stored_user_email_len);
    USER_PASSWORD = Eeprom_read(stored_user_email_password_addr, stored_user_email_password_len);
    DATABASE_URL = Eeprom_read(stored_rtdb_url_addr, stored_rtdb_url_len);
    STORAGE_BUCKET_ID = Eeprom_read(stored_storage_bucket_id_addr, stored_storage_bucket_id_len);
    USER_KEY = Eeprom_read(stored_user_key_addr, stored_user_key_len);
    SHELTER_KEY = Eeprom_read(stored_shelter_key_addr, stored_shelter_key_len);
    userPathRef = "/Owners/" + USER_KEY + "/" + SHELTER_KEY + "/";
    photosPathRef = userPathRef + "Photos/";
    birdFeederPathRef = userPathRef + "Shelter/";
    filePath= USER_KEY + "/" + SHELTER_KEY + "/";
  }
  Serial.println("PARAMETERS");

  Serial.println("API_KEY: " + API_KEY);
  Serial.println("USER_EMAIL: " + USER_EMAIL);
  Serial.println("USER_PASSWORD: " + USER_PASSWORD);
  Serial.println("DATABASE_URL: " + DATABASE_URL);
  Serial.println("STORAGE_BUCKET_ID: " + STORAGE_BUCKET_ID);
  Serial.println("USER_KEY: " + USER_KEY);
  Serial.println("SHELTER_KEY: " + SHELTER_KEY);
  Serial.println(ssid);
  Serial.println(password);

  /* Assign the api key (required) */
  config.api_key = API_KEY.c_str();

  /* Assign the user sign in credentials */
  auth.user.email = USER_EMAIL.c_str();
  auth.user.password = USER_PASSWORD.c_str();

  /* Assign the RTDB URL (required) */
  config.database_url = DATABASE_URL.c_str();
  
  /* Assign the callback function for the long running token generation task */
  config.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h

  Firebase.begin(&config, &auth);
  Firebase.reconnectWiFi(true);

  //Set the size of HTTP response buffers in the case where we want to work with large data.
  fbdo.setResponseSize(1024);

}

boolean Firebase_isReady() {
  //
  // Returns true is Firebase is ready to receive data
  //

  Serial.println("Waiting for Firebase readiness");
  unsigned long elapsedTime = millis();
  while (!Firebase.ready() && (millis() - elapsedTime < FIREBASE_TIMEOUT ) )
    delay(50);
  
  if (Firebase.ready()) 
    return true;
  else
    return false;
  
}

boolean Firebase_uploadImage(camera_fb_t *imageBuffer, String imageName) {
  //
  // Upload the file to Firebase storage
  //

  String imagePath = filePath + imageName;

  if (Firebase.Storage.upload(
                  &fbdo, 
                  STORAGE_BUCKET_ID.c_str(), // Firebase Storage bucket id 
                  imageBuffer->buf, // byte array from ram or flash
                  imageBuffer->len, // size of data in bytes 
                  imagePath.c_str(), // path of remote file stored in the bucket 
                  "image/jpeg" )) { // mime type 
    Serial.println("Image uploaded");
    return true;
  } else {
    Serial.println(fbdo.errorReason());
    return false;
  }
}

String Firebase_getImageURL() {
  //
  //
  //
  return fbdo.downloadURL();
}

boolean Firebase_createPhotoNode(FirebaseJson *json) {
  //
  // Create an new node for the photo on the user path
  //

  if (Firebase.RTDB.pushJSON(&fbdo, photosPathRef, json)) {
    Serial.println("Firebase node created");
    // Get the node's name and add a time  stamp
    String nodePathRef = photosPathRef + fbdo.pushName() + "/datetime";
    if (Firebase.RTDB.setTimestamp(&fbdo, nodePathRef)) {
      Serial.println("Time stamp ok");
    }
    return true;
   } else {
    Serial.println(fbdo.errorReason());
    return false;
   }
}

boolean Firebase_updateUserNodeWithInt(String name, int value) {
 if ( (Firebase.RTDB.setInt(&fbdo, userPathRef + name, value)) ) {
    Serial.println("Firebase user node updated");
    return true;
   } else {
    Serial.println(fbdo.errorReason());
    return false;
   }  
}

int Firebase_getPhotosCount() {

  int photosCount = 1000;   // Set highest number to be returned in case Firebase call fails
  if (Firebase.RTDB.getInt(&fbdo, birdFeederPathRef + "/photosCount")) {
    photosCount = fbdo.to<int>();
    Serial.println("BirdFeeder photos count = " + String(photosCount));
  } 
  return photosCount;
}

int Firebase_getPhotosMaxCount() {

  int photosMaxCount = 0;
  if (Firebase.RTDB.getInt(&fbdo, birdFeederPathRef + "/photosMaxCount")) {
    photosMaxCount = fbdo.to<int>();
    Serial.println("BirdFeeder photos count = " + String(photosMaxCount));
  } 
  return photosMaxCount;
}

CameraSettings Firebase_getCameraSettings() {

  CameraSettings settings;
  if (Firebase.RTDB.getInt(&fbdo, birdFeederPathRef + "/cameraBrightness")) {
    settings.brightness = fbdo.to<int>();
    Serial.println("BirdFeeder camera brightness = " + String(settings.brightness));
  } 
  
  return settings;
}

boolean Firebase_updatePhotoNode(FirebaseJson *json) {
  //
  // Update the photo node
  //  
  String photoPathRef = photosPathRef + "/" + String(1);
  if (Firebase.RTDB.updateNode(&fbdo, photoPathRef, json)) {
    Serial.println("Firebase node created");
    // Get the node's name and add a time  stamp
    String nodePathRef = photoPathRef + "/datetime";
    if (Firebase.RTDB.setTimestamp(&fbdo, nodePathRef)) {
      Serial.println("Time stamp ok");
    }
    return true;
   } else {
    Serial.println(fbdo.errorReason());
    return false;
   }

}

boolean Firebase_updateBirdFeederNode(FirebaseJson *json) {
  
  if (Firebase.RTDB.updateNode(&fbdo, birdFeederPathRef, json)) {
    // Add time stamp
    String nodePathRef = birdFeederPathRef + "/datetime";
    Firebase.RTDB.setTimestamp(&fbdo, nodePathRef);   
    Serial.println("BirdFeeder node updated");
    return true;
  } else {
    Serial.println("BirdFeeder node update failed");
  }
  
}
