// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains client wrappers for the WebSocket host service.
// It is intended for use in Navidrome plugins built with TinyGo.
//
//go:build wasip1

package host

import (
	"encoding/json"
	"errors"

	"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
)

// websocket_connect is the host function provided by Navidrome.
//
//go:wasmimport extism:host/user websocket_connect
func websocket_connect(uint64) uint64

// websocket_sendtext is the host function provided by Navidrome.
//
//go:wasmimport extism:host/user websocket_sendtext
func websocket_sendtext(uint64) uint64

// websocket_sendbinary is the host function provided by Navidrome.
//
//go:wasmimport extism:host/user websocket_sendbinary
func websocket_sendbinary(uint64) uint64

// websocket_closeconnection is the host function provided by Navidrome.
//
//go:wasmimport extism:host/user websocket_closeconnection
func websocket_closeconnection(uint64) uint64

type webSocketConnectRequest struct {
	Url          string            `json:"url"`
	Headers      map[string]string `json:"headers"`
	ConnectionID string            `json:"connectionId"`
}

type webSocketConnectResponse struct {
	NewConnectionID string `json:"newConnectionId,omitempty"`
	Error           string `json:"error,omitempty"`
}

type webSocketSendTextRequest struct {
	ConnectionID string `json:"connectionId"`
	Message      string `json:"message"`
}

type webSocketSendBinaryRequest struct {
	ConnectionID string `json:"connectionId"`
	Data         []byte `json:"data"`
}

type webSocketCloseConnectionRequest struct {
	ConnectionID string `json:"connectionId"`
	Code         int32  `json:"code"`
	Reason       string `json:"reason"`
}

// WebSocketConnect calls the websocket_connect host function.
// Connect establishes a WebSocket connection to the specified URL.
//
// Plugins that use this function must also implement the WebSocketCallback capability
// to receive incoming messages and connection events.
//
// Parameters:
//   - url: The WebSocket URL to connect to (ws:// or wss://)
//   - headers: Optional HTTP headers to include in the handshake request
//   - connectionID: Optional unique identifier for the connection. If empty, one will be generated
//
// Returns the connection ID that can be used to send messages or close the connection,
// or an error if the connection fails.
func WebSocketConnect(url string, headers map[string]string, connectionID string) (string, error) {
	// Marshal request to JSON
	req := webSocketConnectRequest{
		Url:          url,
		Headers:      headers,
		ConnectionID: connectionID,
	}
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return "", err
	}
	reqMem := pdk.AllocateBytes(reqBytes)
	defer reqMem.Free()

	// Call the host function
	responsePtr := websocket_connect(reqMem.Offset())

	// Read the response from memory
	responseMem := pdk.FindMemory(responsePtr)
	responseBytes := responseMem.ReadBytes()

	// Parse the response
	var response webSocketConnectResponse
	if err := json.Unmarshal(responseBytes, &response); err != nil {
		return "", err
	}

	// Convert Error field to Go error
	if response.Error != "" {
		return "", errors.New(response.Error)
	}

	return response.NewConnectionID, nil
}

// WebSocketSendText calls the websocket_sendtext host function.
// SendText sends a text message over an established WebSocket connection.
//
// Parameters:
//   - connectionID: The connection identifier returned by Connect
//   - message: The text message to send
//
// Returns an error if the connection is not found or if sending fails.
func WebSocketSendText(connectionID string, message string) error {
	// Marshal request to JSON
	req := webSocketSendTextRequest{
		ConnectionID: connectionID,
		Message:      message,
	}
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return err
	}
	reqMem := pdk.AllocateBytes(reqBytes)
	defer reqMem.Free()

	// Call the host function
	responsePtr := websocket_sendtext(reqMem.Offset())

	// Read the response from memory
	responseMem := pdk.FindMemory(responsePtr)
	responseBytes := responseMem.ReadBytes()

	// Parse error-only response
	var response struct {
		Error string `json:"error,omitempty"`
	}
	if err := json.Unmarshal(responseBytes, &response); err != nil {
		return err
	}
	if response.Error != "" {
		return errors.New(response.Error)
	}
	return nil
}

// WebSocketSendBinary calls the websocket_sendbinary host function.
// SendBinary sends binary data over an established WebSocket connection.
//
// Parameters:
//   - connectionID: The connection identifier returned by Connect
//   - data: The binary data to send
//
// Returns an error if the connection is not found or if sending fails.
func WebSocketSendBinary(connectionID string, data []byte) error {
	// Marshal request to JSON
	req := webSocketSendBinaryRequest{
		ConnectionID: connectionID,
		Data:         data,
	}
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return err
	}
	reqMem := pdk.AllocateBytes(reqBytes)
	defer reqMem.Free()

	// Call the host function
	responsePtr := websocket_sendbinary(reqMem.Offset())

	// Read the response from memory
	responseMem := pdk.FindMemory(responsePtr)
	responseBytes := responseMem.ReadBytes()

	// Parse error-only response
	var response struct {
		Error string `json:"error,omitempty"`
	}
	if err := json.Unmarshal(responseBytes, &response); err != nil {
		return err
	}
	if response.Error != "" {
		return errors.New(response.Error)
	}
	return nil
}

// WebSocketCloseConnection calls the websocket_closeconnection host function.
// CloseConnection gracefully closes a WebSocket connection.
//
// Parameters:
//   - connectionID: The connection identifier returned by Connect
//   - code: WebSocket close status code (e.g., 1000 for normal closure)
//   - reason: Optional human-readable reason for closing
//
// Returns an error if the connection is not found or if closing fails.
func WebSocketCloseConnection(connectionID string, code int32, reason string) error {
	// Marshal request to JSON
	req := webSocketCloseConnectionRequest{
		ConnectionID: connectionID,
		Code:         code,
		Reason:       reason,
	}
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return err
	}
	reqMem := pdk.AllocateBytes(reqBytes)
	defer reqMem.Free()

	// Call the host function
	responsePtr := websocket_closeconnection(reqMem.Offset())

	// Read the response from memory
	responseMem := pdk.FindMemory(responsePtr)
	responseBytes := responseMem.ReadBytes()

	// Parse error-only response
	var response struct {
		Error string `json:"error,omitempty"`
	}
	if err := json.Unmarshal(responseBytes, &response); err != nil {
		return err
	}
	if response.Error != "" {
		return errors.New(response.Error)
	}
	return nil
}
