/*
 * mata avispas – Flyback high voltage generator controller
 * ESP32‑C3 as Access Point + Web server to configure PWM driving an XY‑MOS driver
 *
 * PWM output: GPIO2 (adjustable via LEDC)
 * Web page: http://192.168.4.1
 * AP SSID: MataAvispas_AP
 * AP Password: avispas123
 *
 * The page lets you set:
 *   - Frequency (Hz)  : 100 – 20000
 *   - Duty cycle (%) : 0 – 100
 *   - Enable/Disable output
 *
 * Uses the ESP32 Arduino core (https://github.com/espressif/arduino-esp32)
 */

#include <WiFi.h>
#include <WebServer.h>

// ==== USER SETTINGS ====
const char* AP_SSID     = "MataAvispas_AP";
const char* AP_PASSWORD = "avispas123";
const uint8_t PWM_GPIO  = 2;          // XY‑MOS INPUT pin
const uint8_t PWM_CHANNEL = 0;        // LEDC channel 0
const uint8_t PWM_RESOLUTION = 10;    // 10‑bit resolution => 0‑1023
// =======================

WebServer server(80);

// Current PWM state
uint32_t pwmFrequency = 1000;   // default 1 kHz
uint32_t pwmDuty      = 512;    // 50 % of 1023
bool     pwmEnabled   = false;

// HTML page (stored in PROGMEM to save RAM)
const char INDEX_HTML[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, charset=utf-8">
  <title>Mata Avispas – PWM Config</title>
  <style>
    body { font-family: Arial, Helvetica, sans-serif; margin: 20px; background:#f4f4f4; }
    .container { max-width: 480px; margin: auto; background:#fff; padding:20px; box-shadow:0 0 10px rgba(0,0,0,.1); border-radius:8px; }
    h1 { color:#2c3e50; text-align:center; }
    label { display:block; margin-top:15px; font-weight:bold; }
    input[type="number"], input[type="range"] { width:100%; padding:8px; margin-top:5px; }
    .btn { display:inline-block; margin-top:20px; padding:10px 20px; background:#27ae60; color:#fff; border:none; border-radius:4px; cursor:pointer; }
    .btn.disabled { background:#95a5a6; cursor:not-allowed; }
    .status { margin-top:15px; padding:10px; background:#ecf0f1; border-radius:4px; }
  </style>
</head>
<body>
<div class="container">
  <h1>Mata Avispas</h1>
  <div class="status" id="status">PWM: <span id="pwmState">OFF</span></div>

  <label for="freq">Frequency (Hz)</label>
  <input type="number" id="freq" min="100" max="20000" value="1000">
  <small>Range: 100 – 20000 Hz</small>

  <label for="duty">Duty cycle (%)</label>
  <input type="range" id="duty" min="0" max="100" value="50">
  <span id="dutyVal">50</span>%

  <label for="enable">Output</label>
  <select id="enable">
    <option value="0">Disabled</option>
    <option value="1">Enabled</option>
  </select>

  <button class="btn" id="sendBtn">Apply Settings</button>
</div>

<script>
  const freqIn   = document.getElementById('freq');
  const dutyIn   = document.getElementById('duty');
  const dutyVal  = document.getElementById('dutyVal');
  const enableIn = document.getElementById('enable');
  const btn      = document.getElementById('sendBtn');
  const status   = document.getElementById('status');
  const pwmState = document.getElementById('pwmState');

  dutyIn.addEventListener('input', () => {
    dutyVal.textContent = dutyIn.value;
  });

  btn.addEventListener('click', () => {
    const data = {
      freq: parseInt(freqIn.value),
      duty: parseInt(dutyIn.value),
      en:   parseInt(enableIn.value)
    };
    fetch('/set', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
    .then(r => r.json())
    .then(resp => {
      if (resp.ok) {
        pwmState.textContent = resp.enabled ? 'ON' : 'OFF';
        status.innerHTML = `PWM: <strong>${resp.enabled ? 'ON' : 'OFF'}</strong> (freq: ${resp.freq} Hz, duty: ${resp.duty}%)`;
        status.style.background = resp.enabled ? '#dff0d8' : '#f2dede';
      } else {
        alert('Error: ' + resp.msg);
      }
    })
    .catch(err => {
      alert('Network error: ' + err);
    });
  });

  // Load current settings on page load
  window.addEventListener('load', () => {
    fetch('/get')
      .then(r => r.json())
      .then(data => {
        freqIn.value = data.freq;
        dutyIn.value = data.duty;
        dutyVal.textContent = data.duty;
        enableIn.value = data.enabled ? '1' : '0';
        pwmState.textContent = data.enabled ? 'ON' : 'OFF';
        status.innerHTML = `PWM: <strong>${data.enabled ? 'ON' : 'OFF'}</strong> (freq: ${data.freq} Hz, duty: ${data.duty}%)`;
        status.style.background = data.enabled ? '#dff0d8' : '#f2dede';
      });
  });
</script>
</body>
</html>
)rawliteral";

void handleRoot() {
  server.send_P(200, "text/html", INDEX_HTML, strlen_P(INDEX_HTML));
}

void handleGet() {
  String json = "{";
  json += "\"freq\":" + String(pwmFrequency) + ",";
  json += "\"duty\":" + String(map(pwmDuty, 0, (1<<PWM_RESOLUTION)-1, 0, 100)) + ",";
  json += "\"enabled\":" + String(pwmEnabled ? "true" : "false");
  json += "}";
  server.send(200, "application/json", json);
}

void handleSet() {
  if (server.method() != HTTP_POST) {
    server.send(405, "text/plain", "Method Not Allowed");
    return;
  }
  if (!server.hasArg("plain")) {
    server.send(400, "text/plain", "Missing JSON body");
    return;
  }
  String body = server.arg("plain");
  // Very simple JSON parsing (expects {"freq":N,"duty":M,"en":0|1})
  int freq = 1000;
  int duty = 50;
  int en   = 0;

  int idx = body.indexOf("\"freq\":");
  if (idx >= 0) {
    String sub = body.substring(idx + 7);
    freq = sub.substring(0, sub.indexOf(",")).toInt();
  }
  idx = body.indexOf("\"duty\":");
  if (idx >= 0) {
    String sub = body.substring(idx + 7);
    duty = sub.substring(0, sub.indexOf(",")).toInt();
  }
  idx = body.indexOf("\"en\":");
  if (idx >= 0) {
    String sub = body.substring(idx + 5);
    en = sub.substring(0, sub.indexOf("}")).toInt();
  }

  // Clamp values
  if (freq < 100) freq = 100;
  if (freq > 20000) freq = 20000;
  if (duty < 0) duty = 0;
  if (duty > 100) duty = 100;

  // Update PWM
  pwmFrequency = freq;
  pwmDuty = map(duty, 0, 100, 0, (1<<PWM_RESOLUTION)-1);
  pwmEnabled = (en == 1);

  if (pwmEnabled) {
    ledcSetup(PWM_CHANNEL, pwmFrequency, PWM_RESOLUTION);
    ledcAttachPin(PWM_GPIO, PWM_CHANNEL);
    ledcWrite(PWM_CHANNEL, pwmDuty);
  } else {
    ledcDetachPin(PWM_GPIO);
  }

  String json = "{";
  json += "\"ok\":true,\"freq\":" + String(pwmFrequency) + ",";
  json += "\"duty\":" + String(duty) + ",";
  json += "\"enabled\":" + String(pwmEnabled ? "true" : "false");
  json += "}";
  server.send(200, "application/json", json);
}

void setup() {
  Serial.begin(115200);
  // Set PWM GPIO as output (safe default)
  pinMode(PWM_GPIO, OUTPUT);
  digitalWrite(PWM_GPIO, LOW);

  // Start AP
  WiFi.mode(WIFI_AP);
  WiFi.softAP(AP_SSID, AP_PASSWORD);
  IPAddress apIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(apIP);

  // Web server routes
  server.on("/", HTTP_GET, handleRoot);
  server.on("/get", HTTP_GET, handleGet);
  server.on("/set", HTTP_POST, handleSet);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
  // Nothing else needed; PWM runs in hardware
}