use crate::{LooperError, Result};
use tokio::net::windows::named_pipe::{NamedPipeServer, ServerOptions};

pub(crate) type PlatformStream = NamedPipeServer;

pub(crate) struct PlatformListener {
    pipe_name: String,
    current_server: Option<NamedPipeServer>,
}

impl PlatformListener {
    pub async fn accept(&mut self) -> Result<PlatformStream> {
        // Create new pipe instance if needed
        if self.current_server.is_none() {
            self.current_server = Some(create_pipe_server(&self.pipe_name)?);
        }

        let server = self.current_server.take().unwrap();
        server
            .connect()
            .await
            .map_err(|_| LooperError::JackConnection(std::panic::Location::caller()))?;

        Ok(server)
    }
}

pub(crate) async fn create_listener(pipe_name: &str) -> Result<PlatformListener> {
    // Convert pipe name to Windows format if needed
    let pipe_path = if pipe_name.starts_with(r"\\.\pipe\") {
        pipe_name.to_string()
    } else {
        format!(r"\\.\pipe\{}", pipe_name)
    };

    Ok(PlatformListener {
        pipe_name: pipe_path,
        current_server: None,
    })
}

fn create_pipe_server(pipe_name: &str) -> Result<NamedPipeServer> {
    ServerOptions::new()
        .first_pipe_instance(false)
        .create(pipe_name)
        .map_err(|_| LooperError::JackConnection(std::panic::Location::caller()))
}
