// Copyright 2020 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 {
    anyhow::Error,
    fidl::endpoints::{create_endpoints, create_proxy},
    fidl_fuchsia_wlan_common::RequestStatus,
    fidl_fuchsia_wlan_policy::{
        AccessPointControllerMarker, AccessPointControllerProxy, AccessPointListenerMarker,
        AccessPointProviderMarker, AccessPointProviderProxy, AccessPointStateUpdatesMarker,
        ConnectivityMode, Credential, NetworkConfig, NetworkIdentifier, OperatingBand,
        OperatingState, SecurityType,
    },
    fuchsia_component::client::connect_to_service,
    futures::TryStreamExt,
};

#[derive(Debug)]
pub struct WlanApPolicyFacade {
    policy_provider: AccessPointProviderProxy,
    ap_controller: AccessPointControllerProxy,
}

impl WlanApPolicyFacade {
    pub fn new() -> Result<WlanApPolicyFacade, Error> {
        let policy_provider = connect_to_service::<AccessPointProviderMarker>()?;
        let (ap_controller, server_end) = create_proxy::<AccessPointControllerMarker>().unwrap();

        // Drop the initial client state update server end.  New update request streams will be
        // created for calls that rely on state changes.
        let (update_client_end, _) = create_endpoints::<AccessPointStateUpdatesMarker>().unwrap();
        let () = policy_provider.get_controller(server_end, update_client_end)?;
        Ok(WlanApPolicyFacade { policy_provider, ap_controller })
    }

    pub async fn start_access_point(
        &self,
        target_ssid: Vec<u8>,
        type_: SecurityType,
        credential: Credential,
        mode: ConnectivityMode,
        band: OperatingBand,
    ) -> Result<(), Error> {
        let listener = connect_to_service::<AccessPointListenerMarker>()?;
        let (client_end, server_end) = create_endpoints::<AccessPointStateUpdatesMarker>().unwrap();
        listener.get_listener(client_end)?;
        let mut server_stream = server_end.into_stream()?;

        match server_stream.try_next().await? {
            Some(update) => {
                let update = update.into_on_access_point_state_update();
                let (_, responder) = match update {
                    Some((update, responder)) => (update, responder),
                    None => return Err(format_err!("AP provider produced invalid update.")),
                };
                let _ = responder.send();
            }
            None => return Err(format_err!("initial steam already busted")),
        }

        let network_id = NetworkIdentifier { ssid: target_ssid.clone(), type_: type_ };

        match self
            .ap_controller
            .start_access_point(
                NetworkConfig {
                    id: Some(network_id),
                    credential: Some(credential),
                    ..NetworkConfig::EMPTY
                },
                mode,
                band,
            )
            .await?
        {
            RequestStatus::Acknowledged => {}
            RequestStatus::RejectedNotSupported => {
                return Err(format_err!("failed to start AP (not supported)"))
            }
            RequestStatus::RejectedIncompatibleMode => {
                return Err(format_err!("failed to start AP (incompatible mode)"))
            }
            RequestStatus::RejectedAlreadyInUse => {
                return Err(format_err!("failed to start AP (already in use)"))
            }
            RequestStatus::RejectedDuplicateRequest => {
                return Err(format_err!("failed to start AP (duplicate request)"))
            }
        }

        while let Some(update_request) = server_stream.try_next().await.unwrap() {
            let update = update_request.into_on_access_point_state_update();
            let (updates, responder) = match update {
                Some((update, responder)) => (update, responder),
                None => return Err(format_err!("AP provider produced invalid update.")),
            };
            let _ = responder.send();

            for update in updates {
                match update.state {
                    Some(state) => match state {
                        OperatingState::Failed => {
                            return Err(format_err!("Failed to start AP."));
                        }
                        OperatingState::Starting => {
                            continue;
                        }
                        OperatingState::Active => return Ok(()),
                    },
                    None => continue,
                }
            }
        }
        return Err(format_err!("AP update stream failed unexpectedly"));
    }

    pub async fn stop_access_point(
        &self,
        target_ssid: Vec<u8>,
        type_: SecurityType,
        credential: Credential,
    ) -> Result<(), Error> {
        let network_id = NetworkIdentifier { ssid: target_ssid.clone(), type_: type_ };
        match self
            .ap_controller
            .stop_access_point(NetworkConfig {
                id: Some(network_id),
                credential: Some(credential),
                ..NetworkConfig::EMPTY
            })
            .await?
        {
            RequestStatus::Acknowledged => Ok(()),
            RequestStatus::RejectedNotSupported => {
                Err(format_err!("Failed to stop AP (not supported)"))
            }
            RequestStatus::RejectedIncompatibleMode => {
                Err(format_err!("Failed to stop AP (incompatible mode)"))
            }
            RequestStatus::RejectedAlreadyInUse => {
                Err(format_err!("Failed to stop AP (already in use)"))
            }
            RequestStatus::RejectedDuplicateRequest => {
                Err(format_err!("Failed to stop AP (duplicate request)"))
            }
        }
    }

    pub async fn stop_all_access_points(&self) -> Result<(), Error> {
        self.ap_controller.stop_all_access_points()?;
        Ok(())
    }
}
