#pragma once

void setRelayDurations(JsonDocument& doc);
void updateRelayTimings();

// - - - - - - - - - - - - - - - - - - - - - - - - - - -

// Handles the incoming payload. Returns it into a "JsonDocument" format.
JsonDocument handleJSON(char * payload) {
	JsonDocument doc;
	DeserializationError error = deserializeJson(doc, payload);
	if (error) {
		Serial.print("deserializeJson() failed: ");
		Serial.println(error.c_str());
	}
	return doc;
}


void replyOnWebSocket(AsyncWebSocketClient *client, String list) {
	client->text(list);
}

// Handles the JSON Commands
void handleCommand(JsonDocument json, AsyncWebSocketClient *client = nullptr){

		String cmd = json["cmd"];
		JsonVariant contents = json["contents"];
		
		if (cmd == "playback") {
			player.command(contents);
		} else if (cmd == "set_melody") {
			player.setMelodyAttributes(contents);
			player.loadMelodyInRAM(melody_steps);
		} else if (cmd == "list_melodies") {
			String list = listFilesAsJson("/melodies");
			PublishMqtt(list.c_str());
			if (client) {
        replyOnWebSocket(client, list);  // Only reply via WS if client exists
    }
		} else if (cmd == "set_relay_timers") {
			updateRelayTimings(contents);
		} else if (cmd == "add_melody"){
			addMelody(contents);
		}	else {
			LOG_WARNING("Unknown Command Received");
		}
		
}


// Subscribes to certain topics on the MQTT Server.
void SuscribeMqtt() {

	  String command = String("vesper/") + DEV_ID + "/control";
    uint16_t command_id = mqttClient.subscribe(command.c_str(), 2);
    LOG_INFO("Subscribing to Command topic, QoS 2, packetId: %d", command_id);

}

// Handles incoming MQTT messages on subscribed topics.
// Could move logic out of this into a dedicated function.
void OnMqttReceived(char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {

	String command = String("vesper/") + DEV_ID + "/control";

	// Don't know what this is. Check it out later.
	//String payloadContent = String(payload).substring(0, len);

	if (String(topic) == command){
		JsonDocument json = handleJSON(payload);
		handleCommand(json);
	}
}


// Handles incoming WebSocket messages on subscribed topics.
// Could move logic out of this into a dedicated function.
void onWebSocketReceived(AsyncWebSocketClient *client, void *arg, uint8_t *data, size_t len) {
    AwsFrameInfo *info = (AwsFrameInfo*)arg;
    if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
        data[len] = '\0'; // Null-terminate the received data
        Serial.printf("Received message: %s\n", (char*)data);

				JsonDocument json = handleJSON((char*)data);
				handleCommand(json, client);
				
    }
}


void onWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
    if (type == WS_EVT_DATA) {
        onWebSocketReceived(client, arg, data, len);
    }
}

// Publishes a message on the MQTT server. Message passed as an argument.
void PublishMqtt(const char * data) {
    String topicData = String("vesper/") + DEV_ID + "/data";
    mqttClient.publish(topicData.c_str(), 0, true, data);
}
