import * as ROSLIB from 'roslib'
import { connectionStatus } from '@/stores/connection-status'

interface BehaviorTreeList {
  tree_ids: Array<string>
}

class Ros {
  private static instance: Ros
  readonly ros: ROSLIB.Ros = new ROSLIB.Ros()
  private readonly url: string = 'http://localhost:3000'
  private timeout: number | null = null

  private reconnectAttempts = 0
  private readonly maxAttempts = 10
  private readonly baseDelay = 500 // 0.5 second

  private constructor() {
    this.connect()
  }

  public static getInstance(): Ros {
    if (!Ros.instance) {
      Ros.instance = new Ros()
    }
    return Ros.instance
  }

  public manualConnect() {
    if (this.timeout) clearTimeout(this.timeout)
    this.connect()
  }

  private connect(): void {
    console.log(`Connecting to ${this.url}...`)

    this.ros.on('connection', () => {
      connectionStatus().rosbridgeConnected = true
      console.log('Connected successfully!')
      this.reconnectAttempts = 0
    })

    this.ros.on('close', (event: ROSLIB.TransportEvent) => {
      connectionStatus().rosbridgeConnected = false
      console.warn('Socket closed:', event)
      this.handleReconnect()
    })

    this.ros.on('error', (error) => {
      console.error('Socket error:', error)
    })
    this.ros.connect(this.url)
  }

  // Backoff algorithm
  private handleReconnect(): void {
    if (this.reconnectAttempts < this.maxAttempts) {
      this.reconnectAttempts++

      const delay = this.baseDelay * Math.pow(2, this.reconnectAttempts - 1)

      console.log(
        `Retrying in ${delay}ms... (Attempt ${this.reconnectAttempts}/${this.maxAttempts})`,
      )

      this.timeout = setTimeout(() => {
        this.timeout = null
        console.log(`Starting attempt [${this.reconnectAttempts}/${this.maxAttempts}]`)
        this.ros.connect(this.url)
      }, delay)
    } else {
      console.error('Max reconnection attempts reached. Please check your connection.')
    }
  }
}

// Usage:
const ros = Ros.getInstance()

export { ros, type BehaviorTreeList }
