/*=========================================================
	MODULE zJsLibrary
	----------------------------------------------------
	Bibliothèque de gestion des connexion WebSocket
	v1.0 - 2025-07-15
=========================================================*/
// wsClient.js
export class WSClient {
	constructor(url) {
		this.url = url;
		this.ws = null;
		this.listeners = new Map(); // { type: callback }
		this.statusHandlers = { open:[], close:[], error:[] };
		this._isOpen = false;

		this.connect();
	}

	get isOpen() {
		return this._isOpen;
	}

	connect() {
		this.ws = new WebSocket(this.url);

		this.ws.addEventListener("open", () => {
			this._isOpen = true;
			console.log("[WS] Connected");
			this._emitStatus("open");
		});

		this.ws.addEventListener("close", () => {
			this._isOpen = false;
			this._emitStatus("close");
			console.warn("[WS] Disconnected, retrying in 2s...");
			setTimeout(() => this.connect(), 2000);
		});

		this.ws.addEventListener("error", (err) => {
			console.error("[WS] Error:", err);
			this._emitStatus("error", err);
		});

		this.ws.addEventListener("message", (event) => {
			try {
				//console.log("WS receive message:", event.data);
				const data = JSON.parse(event.data);
				const type = data.type.toUpperCase();
				//console.log("... type:", type);
				//console.log("... data:", data);

				if (this.listeners.has(type)) {
					this.listeners.get(type)(data.payload);
				} else {
					console.log("WS receive message:", event.data);
					console.warn(`[WS] No handler for message type "${type}"`);
				}
			} catch (err) {
				console.error("[WS] Invalid message format:", event.data);
			}
		});
	}

	send(type, payload = {}) {
		if (this.isOpen) {
			this.ws.send(JSON.stringify({ type, payload }));
		} else {
			console.warn("[WS] Cannot send: socket not open");
		}
	}

	on(type, callback) {
		this.listeners.set(type, callback);
	}

	off(type) {
		this.listeners.delete(type);
	}

	onOpen(callback) {
		this.statusHandlers.open.push(callback);
	}

	onClose(callback) {
		this.statusHandlers.close.push(callback);
	}

	onError(callback) {
		this.statusHandlers.error.push(callback);
	}

	onReconnecting(callback) {
		this.statusHandlers.error.push(callback);
	}

	_emitStatus(type, data) {
		for (const cb of this.statusHandlers[type] || []) {
			cb(data);
   	}
	}
}

export const sendToWebSocket = (type, payload) => {
	console.log("> SendToWebSocket");
	console.log(" ... type:", type);
	console.log(" ... payload:", payload);
	window.top.postMessage({
		action: "ws-send",
		payload: { type, payload }
	}, "*");
}

export const subscribeTo = (type, handler) => {
	window.top.postMessage({
		action: "ws-subscribe",
		payload: { type }
	}, "*");

	window.addEventListener("message", (event) => {
		const { action, payload } = event.data;
		if (action === "ws-message" && payload.type.toUpperCase() === type.toUpperCase()) {
			handler(payload.data);
		}
	});
}

export const unSubscribeTo = (type) => {
	window.top.postMessage({
		action: "ws-unsubscribe",
		payload: { type }
	}, "*");
}

export const subscribeSocketStatus = (handler) => {
	// 1) Demande d’abonnement
	window.top.postMessage({ action: "ws-status-subscribe" }, "*");

	// 2) Réception des mises à jour
	function listener(event) {
		const { action, payload } = event.data || {};
		if (action === "ws-status") {
			handler(payload.status);  // "open" | "closed" | "error" | "reconnecting"
		}
	}
	window.addEventListener("message", listener);

	// 3) Fonction de désinscription facultative
	return () => {
		window.top.postMessage({ action: "ws-status-unsubscribe" }, "*");
		window.removeEventListener("message", listener);
	};
}
