// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    crate::client::QmiClient,
    crate::errors::QmuxError,
    crate::transport::QmiTransport,
    anyhow::Error,
    fidl::endpoints::{ClientEnd, ServerEnd},
    fidl_fuchsia_telephony_ril::*,
    fuchsia_async as fasync,
    fuchsia_component::server::ServiceFs,
    fuchsia_syslog::{self as syslog, macros::*},
    fuchsia_zircon as zx,
    futures::lock::Mutex,
    futures::{
        future::Future,
        task::{AtomicWaker, Context, Poll},
        StreamExt, TryFutureExt, TryStreamExt,
    },
    qmi_protocol::QmiResult,
    qmi_protocol::*,
    std::pin::Pin,
    std::sync::Arc,
};

mod client;
mod errors;
mod transport;

type QmiModemPtr = Arc<Mutex<QmiModem>>;

struct QmiTransportMgr {
    transport: Option<Arc<QmiTransport>>,
    waker: AtomicWaker,
}

impl QmiTransportMgr {
    pub fn new() -> QmiTransportMgr {
        QmiTransportMgr { transport: None, waker: AtomicWaker::new() }
    }

    pub fn set_transport(&mut self, transport: QmiTransport) {
        self.transport = Some(Arc::new(transport));
        self.waker.wake();
    }
}

impl Future for &QmiTransportMgr {
    type Output = Arc<QmiTransport>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match self.transport {
            Some(ref transport) => Poll::Ready(transport.clone()),
            None => {
                self.waker.register(cx.waker());
                Poll::Pending
            }
        }
    }
}

pub struct QmiModem {
    inner: QmiTransportMgr,
}

impl QmiModem {
    pub fn new() -> Self {
        QmiModem { inner: QmiTransportMgr::new() }
    }

    pub fn connect_transport(&mut self, chan: zx::Channel) -> bool {
        fx_log_info!("Connecting the transport");
        match fasync::Channel::from_channel(chan) {
            Ok(chan) => {
                if chan.is_closed() {
                    fx_log_err!("The transport channel is not open");
                    return false;
                }
                self.inner.set_transport(QmiTransport::new(chan));
                true
            }
            Err(_) => {
                fx_log_err!("Failed to convert a zircon channel to a fasync one");
                false
            }
        }
    }

    pub async fn create_client(&self) -> QmiClient {
        let transport = (&self.inner).await;
        let client = QmiClient::new(transport);
        client
    }
}

/// Craft a QMI Query given a handle and a client connection. Handles common error paths.
/// For more specialized interactions with the modem, prefer to call `client.send_msg()` directly.
macro_rules! qmi_query {
    ($responder:expr, $client:expr, $query:expr) => {{
        let resp: Result<QmiResult<_>, QmuxError> = $client.send_msg($query).await;
        match resp {
            Ok(qmi_result) => {
                match qmi_result {
                    Ok(qmi) => qmi,
                    Err(e) => {
                        fx_log_err!("Unknown Error: {:?}", e);
                        // TODO(bwb): Define conversion trait between errors and RIL errors
                        return $responder.send(&mut Err(RilError::UnknownError));
                    }
                }
            }
            Err(e) => {
                fx_log_err!("Transport Error: {}", e);
                return $responder.send(&mut Err(RilError::TransportError));
            }
        }
    }};
}

struct FrilService;
impl FrilService {
    pub fn spawn(modem: QmiModemPtr, stream: RadioInterfaceLayerRequestStream) {
        let server = async move {
            let client = {
                let modem_lock = modem.lock().await;
                Arc::new(modem_lock.create_client().await)
            };
            stream
                .try_for_each(move |req| Self::handle_request(client.clone(), req))
                .unwrap_or_else(|e| fx_log_err!("Error running {:?}", e))
                .await
        };
        fasync::spawn(server);
    }

    async fn handle_request(
        client: Arc<QmiClient>,
        request: RadioInterfaceLayerRequest,
    ) -> Result<(), fidl::Error> {
        match request {
            RadioInterfaceLayerRequest::GetSignalStrength { responder } => {
                let resp = qmi_query!(responder, client, NAS::GetSignalStrengthReq::new());
                if resp.radio_interface != 0x08 {
                    responder.send(&mut Err(RilError::UnsupportedNetworkType))?
                } else {
                    responder.send(&mut Ok(resp.signal_strength as f32))?
                }
            }
            RadioInterfaceLayerRequest::GetNetworkSettings { responder } => {
                let packet = qmi_query!(responder, client, WDS::GetCurrentSettingsReq::new(58160));
                responder.send(&mut Ok(NetworkSettings {
                    ip_v4_addr: packet.ipv4_addr.unwrap(),
                    ip_v4_dns: packet.ipv4_dns.unwrap(),
                    ip_v4_subnet: packet.ipv4_subnet.unwrap(),
                    ip_v4_gateway: packet.ipv4_gateway.unwrap(),
                    mtu: packet.mtu.unwrap(),
                }))?
            }
            RadioInterfaceLayerRequest::StartNetwork { apn, responder } => {
                let packet = qmi_query!(
                    responder,
                    client,
                    WDS::StartNetworkInterfaceReq::new(Some(apn), Some(4))
                );
                let (server_chan, client_chan) = zx::Channel::create().unwrap();
                let server_end = ServerEnd::<NetworkConnectionMarker>::new(server_chan.into());
                client
                    .set_data_connection(client::Connection {
                        pkt_handle: packet.packet_data_handle,
                        conn: server_end,
                    })
                    .await;
                let client_end = ClientEnd::<NetworkConnectionMarker>::new(client_chan.into());
                responder.send(&mut Ok(client_end))?
            }
            RadioInterfaceLayerRequest::GetDeviceIdentity { responder } => {
                let resp = qmi_query!(responder, client, DMS::GetDeviceSerialNumbersReq::new());
                responder.send(&mut Ok(resp.imei))?
            }
            RadioInterfaceLayerRequest::RadioPowerStatus { responder } => {
                let resp = qmi_query!(responder, client, DMS::GetOperatingModeReq::new());
                if resp.operating_mode == 0x00 {
                    responder.send(&mut Ok(RadioPowerState::On))?
                } else {
                    responder.send(&mut Ok(RadioPowerState::Off))?
                }
            }
            RadioInterfaceLayerRequest::RawCommand { command: _command, responder } => {
                responder.send(&mut Err(RilError::UnknownError))?
            }
        }
        Ok(())
    }
}

#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
    syslog::init_with_tags(&["ril-qmi"]).expect("Can't init logger");
    fx_log_info!("Starting ril-qmi...");

    let modem = Arc::new(Mutex::new(QmiModem::new()));
    let modem_setup = modem.clone();

    let mut fs = ServiceFs::new_local();
    fs.dir("svc")
        .add_fidl_service(move |stream| {
            fx_log_info!("New client connecting to the Fuchsia RIL");
            FrilService::spawn(modem.clone(), stream)
        })
        .add_fidl_service(move |mut stream: SetupRequestStream| {
            let modem = modem_setup.clone();
            fasync::spawn(async move {
                let res = stream.next().await.unwrap();
                if let Ok(SetupRequest::ConnectTransport { channel, responder }) = res {
                    let mut lock = modem.lock().await;
                    let status = lock.connect_transport(channel);
                    fx_log_info!("Connecting the service to the transport driver: {}", status);
                    if status {
                        let _ = responder.send(&mut Ok(()));
                    } else {
                        let _ = responder.send(&mut Err(RilError::TransportError));
                    }
                }
            });
        });

    fs.take_and_serve_directory_handle()?;

    Ok(fs.collect::<()>().await)
}
