// Generated by smithplates HTTP codegen. Do not edit.

import type { PetEventsInput } from "generated/petstore/api/petEventsInput";
import { serializePetEventsInput } from "generated/petstore/api/petEventsInput";
import type { PetEventsOutput } from "generated/petstore/api/petEventsOutput";
import { parsePetEventsOutput } from "generated/petstore/api/petEventsOutput";

export class PetstoreWebsocketClient {
  private readonly baseUrl: string;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl.replace(/\/+$/, "");
  }

  connectPetEvents(): PetEventsConnection {
    const socket = new WebSocket(`${this.baseUrl}/pets/events`);
    return new PetEventsConnection(socket);
  }
}

export class PetEventsConnection {
  private readonly socket: WebSocket;

  constructor(socket: WebSocket) {
    this.socket = socket;
  }

  send(message: PetEventsInput): void {
    this.socket.send(JSON.stringify(serializePetEventsInput(message)));
  }

  onMessage(handler: (message: PetEventsOutput) => void): () => void {
    const listener = (event: MessageEvent) => {
      const data =
        typeof event.data === "string"
          ? event.data
          : new TextDecoder().decode(event.data);
      handler(parsePetEventsOutput(JSON.parse(data)));
    };
    this.socket.addEventListener("message", listener);
    return () => this.socket.removeEventListener("message", listener);
  }

  onClose(handler: (event: { code: number; reason: string; wasClean: boolean }) => void): () => void {
    this.socket.addEventListener("close", handler);
    return () => this.socket.removeEventListener("close", handler);
  }

  onError(handler: (event: Event) => void): () => void {
    this.socket.addEventListener("error", handler);
    return () => this.socket.removeEventListener("error", handler);
  }

  close(): void {
    this.socket.close();
  }
}
