'use strict';
// Relay-agent: maakt de lokale baan bedienbaar via de webversie op p33k.nl.
// Verbindt UITGAAND met de relay (geen poorten openzetten). Pusht berichten naar de relay
// en haalt commando's op die het via de meegegeven handler uitvoert.
//
// Activeren: in data/config.json een "relayCode" zetten (zelfde code in de webversie invullen).
const https = require('https');
const http = require('http');

class RelayAgent {
  constructor(opts) {
    this.code = opts.code;
    this.url = opts.url || 'https://modelrailpro.com/relay.php';
    this.onCmd = opts.onCmd || (() => {});
    this.log = opts.log || (() => {});
    this.inSeq = 0;
    this.queue = [];     // te pushen berichten
    this.started = false;
  }

  start() {
    if (this.started || !this.code) return;
    this.started = true;
    this.log('[relay] agent gestart — koppelcode actief, webversie kan nu verbinden');
    this._flushLoop();
    this._pollLoop();
  }

  stop() { this.started = false; this.queue = []; this.log('[relay] agent gestopt'); }

  // berichten klaarzetten om te pushen (van de server: state/roster/license/log/...)
  push(msg) { if (this.started) this.queue.push(msg); }

  _req(method, qs, body) {
    return new Promise((resolve) => {
      const full = this.url + '?' + qs;
      const lib = full.startsWith('https') ? https : http;
      const data = body !== undefined ? JSON.stringify(body) : null;
      const req = lib.request(full, { method, timeout: 8000, headers: data ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } : {} }, (res) => {
        let b = ''; res.on('data', (c) => b += c); res.on('end', () => { try { resolve(JSON.parse(b)); } catch (_) { resolve(null); } });
      });
      req.on('error', () => resolve(null));
      req.on('timeout', () => { req.destroy(); resolve(null); });
      if (data) req.write(data);
      req.end();
    });
  }

  async _flushLoop() {
    while (this.started) {
      if (this.queue.length) {
        const batch = this.queue.splice(0, 20);
        await this._req('POST', 'code=' + encodeURIComponent(this.code) + '&role=push', batch);
      }
      await new Promise((r) => setTimeout(r, 250));
    }
  }

  async _pollLoop() {
    while (this.started) {
      const r = await this._req('GET', 'code=' + encodeURIComponent(this.code) + '&role=in&since=' + this.inSeq);
      if (r && Array.isArray(r.cmds)) {
        this.inSeq = r.seq || this.inSeq;
        for (const c of r.cmds) { try { this.onCmd(c); } catch (_) {} }
      }
      await new Promise((res) => setTimeout(res, 300));
    }
  }
}

module.exports = { RelayAgent };
