//! WebSocket sender implementation for web-sys backend.

use crate::{Message, Result};
use crate::traits::WebSocketSenderTrait;
use std::future::Future;

/// WebSocket sender. Also responsible for closing the connection.
#[derive(Debug, Clone)]
pub struct WebSocketSender {
    pub(crate) websocket: web_sys::WebSocket,
}

impl WebSocketSenderTrait for WebSocketSender {
    fn close(&mut self, message: Option<(u16, String)>) -> impl Future<Output = Result<()>> {
        async move {
            self.send(Message::Close(message)).await
        }
    }

    fn send(&mut self, message: Message) -> impl Future<Output = Result<()>> {
        async move {
            if self.websocket.ready_state() == web_sys::WebSocket::OPEN {
                match message {
                    Message::Text(text) => {
                        self.websocket.send_with_str(&text)
                            .map_err(|error| crate::error::Error::SendError(error))
                    },
                    Message::Binary(binary) => {
                        self.websocket.send_with_u8_array(&binary)
                            .map_err(|error| crate::error::Error::SendError(error))
                    },
                    Message::Close(close) => {
                        if let Some((code, reason)) = close {
                            self.websocket.close_with_code_and_reason(code, &reason)
                                .map_err(|error| crate::error::Error::SendError(error))
                        } else {
                            self.websocket.close()
                                .map_err(|error| crate::error::Error::SendError(error))
                        }
                    }
                }
            } else {
                Err(crate::error::Error::SendError("Sending while the socket is not open is not allowed.".into()))
            }                
        }
    }
}

