const WebSocket = require('ws');

class WebSocketClient {
    constructor(url, options = {},wsListener) {
        this.url = url;
        this.options = options;
        this.wsListener = wsListener
        this.reconnectDelay = options.reconnectDelay || 5000;
        this.heartbeatInterval = options.heartbeatInterval || 30000;
        this.heartbeatTimeout = options.heartbeatTimeout || 5000;
        
        this.ws = null;
        this.heartbeatTimer = null;
        this.reconnectTimer = null;
        this.heartbeatTimeoutTimer = null;
        
        this.connect();
    }

    connect() {
        try {
            this.ws = new WebSocket(this.url);
            
            this.ws.on('open', () => {
                console.log('WebSocket connected');
                this.startHeartbeat();
                this.wsListener.onOpen(this.ws)
            });

            this.ws.on('message', (data) => {
                this.handleMessage(data);
            });

            this.ws.on('close', () => {
                console.log('WebSocket closed');
                this.cleanup();
                this.scheduleReconnect();
                this.wsListener.onClosing()
            });

            this.ws.on('error', (error) => {
                console.error('WebSocket error:', error);
                this.cleanup();
                this.scheduleReconnect();
                this.wsListener.onFailure()
            });

        } catch (error) {
            console.error('Connection error:', error);
            this.scheduleReconnect();
            this.wsListener.onFailure()
        }
    }

    handleMessage(data) {
        // Handle incoming messages
        const message = data.toString();
        console.log('Received:', message);
        // If received pong message
        if (message === 'pong') {
            clearTimeout(this.heartbeatTimeoutTimer);
            return
        }
        this.wsListener.onMessage(this.ws,message)
        // Handle other messages
    }

    startHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            if (this.ws.readyState === WebSocket.OPEN) {
                // Send ping message
                this.ws.send('ping');
                
                // Set timeout for pong response
                this.heartbeatTimeoutTimer = setTimeout(() => {
                    console.log('Heartbeat timeout');
                    this.ws.terminate();
                }, this.heartbeatTimeout);
            }
        }, this.heartbeatInterval);
    }

    cleanup() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
        if (this.heartbeatTimeoutTimer) {
            clearTimeout(this.heartbeatTimeoutTimer);
            this.heartbeatTimeoutTimer = null;
        }
        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer);
            this.reconnectTimer = null;
        }
    }

    scheduleReconnect() {
        if (!this.reconnectTimer) {
            this.reconnectTimer = setTimeout(() => {
                console.log('Attempting to reconnect...');
                this.connect();
            }, this.reconnectDelay);
        }
    }

    close() {
        this.cleanup();
        if (this.ws) {
            this.ws.close();
        }
    }

    sendMsg(msg){
        if (this.ws) {
            this.ws.send(msg);
        }
    }
}

module.exports = WebSocketClient;