# Code generated by ndpgen. DO NOT EDIT.
#
# This file contains client wrappers for the {{.Service.Name}} host service.
# It is intended for use in Navidrome plugins built with extism-py.
#
# IMPORTANT: Due to a limitation in extism-py, you cannot import this file directly.
# The @extism.import_fn decorators are only detected when defined in the plugin's
# main __init__.py file. Copy the needed functions from this file into your plugin.

from dataclasses import dataclass
from typing import Any{{- if .Service.HasRawMethods}}, Tuple{{end}}

import extism
import json
{{- if .Service.HasRawMethods}}
import struct
{{- end}}


class HostFunctionError(Exception):
    """Raised when a host function returns an error."""
    pass

{{- /* Generate raw host function imports */ -}}
{{range .Service.Methods}}


@extism.import_fn("extism:host/user", "{{exportName .}}")
def _{{exportName .}}(offset: int) -> int:
    """Raw host function - do not call directly."""
    ...
{{- end}}
{{- /* Generate dataclasses for multi-value returns */ -}}
{{range .Service.Methods}}
{{- if and .NeedsResultClass (not .Raw)}}


@dataclass
class {{pythonResultType .}}:
    """Result type for {{pythonFunc .}}."""
{{- range .Returns}}
    {{.PythonName}}: {{.PythonType}}
{{- end}}
{{- end}}
{{- end}}
{{- /* Generate wrapper functions */ -}}
{{range .Service.Methods}}


def {{pythonFunc .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.PythonName}}: {{$p.PythonType}}{{end}}){{if .Raw}} -> Tuple[str, bytes]{{else if .NeedsResultClass}} -> {{pythonResultType .}}{{else if .HasReturns}} -> {{(index .Returns 0).PythonType}}{{else}} -> None{{end}}:
    """{{if .Doc}}{{.Doc}}{{else}}Call the {{exportName .}} host function.{{end}}
{{- if .HasParams}}

    Args:
{{- range .Params}}
        {{.PythonName}}: {{.PythonType}} parameter.
{{- end}}
{{- end}}
{{- if .Raw}}

    Returns:
        Tuple of (content_type, data) with the raw binary response.
{{- else if .HasReturns}}

    Returns:
{{- if .NeedsResultClass}}
        {{pythonResultType .}} containing{{range .Returns}} {{.PythonName}},{{end}}.
{{- else}}
        {{(index .Returns 0).PythonType}}: The result value.
{{- end}}
{{- end}}

    Raises:
        HostFunctionError: If the host function returns an error.
    """
{{- if .HasParams}}
    request = {
{{- range .Params}}
        "{{.JSONName}}": {{.PythonName}},
{{- end}}
    }
    request_bytes = json.dumps(request).encode("utf-8")
{{- else}}
    request_bytes = b"{}"
{{- end}}
    request_mem = extism.memory.alloc(request_bytes)
    response_offset = _{{exportName .}}(request_mem.offset)
    response_mem = extism.memory.find(response_offset)
{{- if .Raw}}
    response_bytes = response_mem.bytes()

    if len(response_bytes) == 0:
        raise HostFunctionError("empty response from host")
    if response_bytes[0] == 0x01:
        raise HostFunctionError(response_bytes[1:].decode("utf-8"))
    if response_bytes[0] != 0x00:
        raise HostFunctionError("unknown response status")
    if len(response_bytes) < 5:
        raise HostFunctionError("malformed raw response: incomplete header")
    ct_len = struct.unpack(">I", response_bytes[1:5])[0]
    if len(response_bytes) < 5 + ct_len:
        raise HostFunctionError("malformed raw response: content-type overflow")
    content_type = response_bytes[5:5 + ct_len].decode("utf-8")
    data = response_bytes[5 + ct_len:]
    return content_type, data
{{- else}}
    response = json.loads(extism.memory.string(response_mem))
{{if .HasError}}
    if response.get("error"):
        raise HostFunctionError(response["error"])
{{end}}
{{- if .NeedsResultClass}}
    return {{pythonResultType .}}(
{{- range .Returns}}
        {{.PythonName}}=response.get("{{.JSONName}}"{{pythonDefault .}}),
{{- end}}
    )
{{- else if .HasReturns}}
    return response.get("{{(index .Returns 0).JSONName}}"{{pythonDefault (index .Returns 0)}})
{{- end}}
{{- end}}
{{- end}}
