//! This module contains code used from message-based communication between threads.

use crate::core::fingerprinting::signature_format::DecodedSignature;
#[cfg(feature = "gui")]
use crate::core::preferences::Preferences;

use std::thread;

pub fn spawn_big_thread<F, T>(argument: F)
where
    F: std::ops::FnOnce() -> T,
    F: std::marker::Send + 'static,
    T: std::marker::Send + 'static,
{
    thread::Builder::new()
        .stack_size(32 * 1024 * 1024)
        .spawn(argument)
        .unwrap();
}

#[derive(Debug)]
pub struct SongRecognizedMessage {
    pub artist_name: String,
    pub album_name: Option<String>,
    pub song_name: String,
    pub cover_image: Option<Vec<u8>>,

    // Used only in the CSV export for now:
    pub track_key: String,
    pub release_year: Option<String>,
    pub genre: Option<String>,

    pub shazam_json: String,
}

#[derive(Debug)]
pub struct DeviceListItem {
    pub inner_name: String,
    pub display_name: String,
    // The checkbox option on the UI should select the first monitor
    // device present in the combo box, when specified
    pub is_monitor: bool,
}

#[derive(Debug)]
pub enum GUIMessage {
    ErrorMessage(String),
    ShowWindow,
    QuitApplication,
    // A list of audio devices, received from the microphone thread
    // because CPAL can't be called from the same thread as the GUI
    // under Windows
    DevicesList(Vec<DeviceListItem>),
    #[cfg(feature = "gui")]
    UpdatePreference(Preferences),
    NetworkStatus(bool),  // Is the network reachable?
    RateLimitState(bool), // Are we rate-limited?
    #[cfg(feature = "gui")]
    WipeSongHistory,
    #[cfg(feature = "gui")]
    AppendToLog(String),
    MicrophoneRecording,
    MicrophoneVolumePercent(f32),
    SongRecognized(Box<SongRecognizedMessage>),
}

pub enum MicrophoneMessage {
    MicrophoneRecordStart(String), // The argument is the audio device name
    MicrophoneRecordSetDevice(String), // The argument is the audio device name (with an initialization delay)
    RefreshDevices,
    MicrophoneRecordStop,
    ProcessingDone,
}

pub enum ProcessingMessage {
    ProcessAudioFile(String),
    ProcessAudioSamples(Vec<f32>), // Prefer to use heap across threads to avoid stack overflow
}

pub enum HTTPMessage {
    RecognizeSignature(Box<DecodedSignature>),
}
