/// © MiroZ 2024

#include "App.h"
#include "Settings.h"
#include <WiFi.h>
#include "ReaderWriter.h"

#include "Ble.h"

static const char * TAG = "ble";

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

Ble::Ble(App & app) : m_app(app)
{
	m_rw = new ReaderWriter(512);
}

void Ble::start()
{
	ESP_LOGW(TAG, "Starting BLE...");

	uint8_t wifi_mac[8];
	esp_read_mac(wifi_mac, ESP_MAC_WIFI_STA);

	sprintf(m_name, "WP_%u_%02x%02x%02x", SETTINGS.device.id, wifi_mac[3], wifi_mac[4], wifi_mac[5]);

	NimBLEDevice::init(m_name);

	NimBLEDevice::setPower(ESP_PWR_LVL_P9);
	// NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_SC);
	m_server = NimBLEDevice::createServer();

	m_server->setCallbacks(this);
	m_service = m_server->createService(SERVICE_UUID);
	m_characteristic = m_service->createCharacteristic(CHARACTERISTIC_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);
	m_characteristic->setCallbacks(this);
	// NimBLE2904 * desc = (NimBLE2904*)m_characteristic->createDescriptor("2904");
	// desc->setFormat(NimBLE2904::FORMAT_UTF8);
	// m_characteristic->addDescriptor(desc);

	m_service->start();

	m_advertising = NimBLEDevice::getAdvertising();
	m_advertising->addServiceUUID(m_service->getUUID());
	m_advertising->start();
}

void Ble::onConnect(NimBLEServer* pServer) 
{
	// uint16_t id = pServer->getConnId();
	// ESP_LOGI(TAG, "%d connected", id);
	ESP_LOGI(TAG, "connected");
}

void Ble::onDisconnect(NimBLEServer* pServer)
{
	// uint16_t id = pServer->getConnId();
	// ESP_LOGI(TAG, "%d disconnected", id);
	NimBLEDevice::startAdvertising();
	// m_advertising->start();
}

void Ble::onRead(NimBLECharacteristic* pCharacteristic)
{
	int a = 1234;
	pCharacteristic->setValue(a);
	ESP_LOGI(TAG, "onRead hello");
}

char buf[512];

void Ble::onWrite(NimBLECharacteristic* pCharacteristic)
{
	uint32_t len = pCharacteristic->getDataLength();
	memcpy(buf, pCharacteristic->getValue().c_str(), len);
	buf[len] = 0;

	ESP_LOGI(TAG, "'%s'", buf);

	Parser p((char *)buf, "|");
	char buffer[80];
	p.getElementAt(0, buffer, sizeof(buffer));

	ESP_LOGI(TAG, "command '%s'", buffer);

	if(buffer[0] == 'w')
	{
		ESP_LOGI(TAG, "Scanning wifi networks...");

		int num_networks = WiFi.scanNetworks(false, false, false, 0);

		m_rw->reset();
		m_rw->appendf("w|%d|", num_networks);
		for(int n = 0; n < num_networks; n++)
		{
			m_rw->append(WiFi.SSID(n).c_str());
			m_rw->append(",");
			m_rw->appendf("%d", WiFi.RSSI(n));
			if(n < num_networks-1)
				m_rw->append("|");
		}
		ESP_LOGI(TAG, "'%s'", m_rw->getBuffer());
		pCharacteristic->setValue((uint8_t*)m_rw->getBuffer(), m_rw->getLen());
		pCharacteristic->notify();
	}
	else if(buffer[0] == 'd')
	{
		SETTINGS.wifi.num = 0;
		SETTINGS_SAVE;
		esp_restart();
	}
}
