// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains export wrappers for the SonicSimilarity capability.
// It is intended for use in Navidrome plugins built with extism-pdk.

use serde::{Deserialize, Serialize};

// Helper functions for skip_serializing_if with numeric types
#[allow(dead_code)]
fn is_zero_i32(value: &i32) -> bool { *value == 0 }
#[allow(dead_code)]
fn is_zero_u32(value: &u32) -> bool { *value == 0 }
#[allow(dead_code)]
fn is_zero_i64(value: &i64) -> bool { *value == 0 }
#[allow(dead_code)]
fn is_zero_u64(value: &u64) -> bool { *value == 0 }
#[allow(dead_code)]
fn is_zero_f32(value: &f32) -> bool { *value == 0.0 }
#[allow(dead_code)]
fn is_zero_f64(value: &f64) -> bool { *value == 0.0 }
/// FindSonicPathRequest represents the FindSonicPathRequest data structure.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FindSonicPathRequest {
    #[serde(default)]
    pub start_song: SongRef,
    #[serde(default)]
    pub end_song: SongRef,
    #[serde(default)]
    pub count: i32,
}
/// GetSonicSimilarTracksRequest represents the GetSonicSimilarTracksRequest data structure.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetSonicSimilarTracksRequest {
    #[serde(default)]
    pub song: SongRef,
    #[serde(default)]
    pub count: i32,
}
/// SongRef is a reference to a song with metadata for matching.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SongRef {
    /// ID is the internal Navidrome mediafile ID (if known).
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub id: String,
    /// Name is the song name.
    #[serde(default)]
    pub name: String,
    /// MBID is the MusicBrainz ID for the song.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub mbid: String,
    /// ISRC is the International Standard Recording Code for the song.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub isrc: String,
    /// Artist is the artist name.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub artist: String,
    /// ArtistMBID is the MusicBrainz artist ID.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub artist_mbid: String,
    /// Album is the album name.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub album: String,
    /// AlbumMBID is the MusicBrainz release ID.
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub album_mbid: String,
    /// Duration is the song duration in seconds.
    #[serde(default, skip_serializing_if = "is_zero_f32")]
    pub duration: f32,
}
/// SonicMatch represents the SonicMatch data structure.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SonicMatch {
    #[serde(default)]
    pub song: SongRef,
    #[serde(default)]
    pub similarity: f64,
}
/// SonicSimilarityResponse represents the SonicSimilarityResponse data structure.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SonicSimilarityResponse {
    #[serde(default)]
    pub matches: Vec<SonicMatch>,
}

/// Error represents an error from a capability method.
#[derive(Debug)]
pub struct Error {
    pub message: String,
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl std::error::Error for Error {}

impl Error {
    pub fn new(message: impl Into<String>) -> Self {
        Self { message: message.into() }
    }
}

/// SonicSimilarity requires all methods to be implemented.
/// SonicSimilarity provides audio-similarity based track discovery.
pub trait SonicSimilarity {
    /// GetSonicSimilarTracks
    fn get_sonic_similar_tracks(&self, req: GetSonicSimilarTracksRequest) -> Result<SonicSimilarityResponse, Error>;
    /// FindSonicPath
    fn find_sonic_path(&self, req: FindSonicPathRequest) -> Result<SonicSimilarityResponse, Error>;
}

/// Register all exports for the SonicSimilarity capability.
/// This macro generates the WASM export functions for all trait methods.
#[macro_export]
macro_rules! register_sonicsimilarity {
    ($plugin_type:ty) => {
        #[extism_pdk::plugin_fn]
        pub fn nd_get_sonic_similar_tracks(
            req: extism_pdk::Json<$crate::sonicsimilarity::GetSonicSimilarTracksRequest>
        ) -> extism_pdk::FnResult<extism_pdk::Json<$crate::sonicsimilarity::SonicSimilarityResponse>> {
            let plugin = <$plugin_type>::default();
            let result = $crate::sonicsimilarity::SonicSimilarity::get_sonic_similar_tracks(&plugin, req.into_inner())?;
            Ok(extism_pdk::Json(result))
        }
        #[extism_pdk::plugin_fn]
        pub fn nd_find_sonic_path(
            req: extism_pdk::Json<$crate::sonicsimilarity::FindSonicPathRequest>
        ) -> extism_pdk::FnResult<extism_pdk::Json<$crate::sonicsimilarity::SonicSimilarityResponse>> {
            let plugin = <$plugin_type>::default();
            let result = $crate::sonicsimilarity::SonicSimilarity::find_sonic_path(&plugin, req.into_inner())?;
            Ok(extism_pdk::Json(result))
        }
    };
}
