// Copyright 2019 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::fidl_processor::process_stream, crate::switchboard::base::*,
    crate::switchboard::hanging_get_handler::Sender, fidl::endpoints::ServiceMarker,
    fidl_fuchsia_media::AudioRenderUsage, fidl_fuchsia_settings::*, fuchsia_async as fasync,
    futures::future::LocalBoxFuture, futures::prelude::*,
};

impl Sender<AudioSettings> for AudioWatchResponder {
    fn send_response(self, data: AudioSettings) {
        self.send(&mut Ok(data)).log_fidl_response_error(AudioMarker::DEBUG_NAME);
    }
}

impl From<SettingResponse> for AudioSettings {
    fn from(response: SettingResponse) -> Self {
        if let SettingResponse::Audio(info) = response {
            let mut streams = Vec::new();
            for stream in info.streams.iter() {
                streams.push(AudioStreamSettings::from(stream.clone()));
            }

            let mut audio_input = AudioInput::empty();
            audio_input.muted = Some(info.input.mic_mute);

            let mut audio_settings = AudioSettings::empty();
            audio_settings.streams = Some(streams);
            audio_settings.input = Some(audio_input);
            audio_settings
        } else {
            panic!("incorrect value sent to audio");
        }
    }
}

impl From<AudioStream> for AudioStreamSettings {
    fn from(stream: AudioStream) -> Self {
        AudioStreamSettings {
            stream: Some(AudioRenderUsage::from(stream.stream_type)),
            source: Some(AudioStreamSettingSource::from(stream.source)),
            user_volume: Some(Volume {
                level: Some(stream.user_volume_level),
                muted: Some(stream.user_volume_muted),
            }),
        }
    }
}

impl From<AudioRenderUsage> for AudioStreamType {
    fn from(usage: AudioRenderUsage) -> Self {
        match usage {
            AudioRenderUsage::Background => AudioStreamType::Background,
            AudioRenderUsage::Media => AudioStreamType::Media,
            AudioRenderUsage::Interruption => AudioStreamType::Interruption,
            AudioRenderUsage::SystemAgent => AudioStreamType::SystemAgent,
            AudioRenderUsage::Communication => AudioStreamType::Communication,
        }
    }
}

impl From<AudioStreamType> for AudioRenderUsage {
    fn from(usage: AudioStreamType) -> Self {
        match usage {
            AudioStreamType::Background => AudioRenderUsage::Background,
            AudioStreamType::Media => AudioRenderUsage::Media,
            AudioStreamType::Interruption => AudioRenderUsage::Interruption,
            AudioStreamType::SystemAgent => AudioRenderUsage::SystemAgent,
            AudioStreamType::Communication => AudioRenderUsage::Communication,
        }
    }
}

impl From<AudioStreamSettingSource> for AudioSettingSource {
    fn from(source: AudioStreamSettingSource) -> Self {
        match source {
            AudioStreamSettingSource::User => AudioSettingSource::User,
            AudioStreamSettingSource::System => AudioSettingSource::System,
        }
    }
}

impl From<AudioSettingSource> for AudioStreamSettingSource {
    fn from(source: AudioSettingSource) -> Self {
        match source {
            AudioSettingSource::User => AudioStreamSettingSource::User,
            AudioSettingSource::System => AudioStreamSettingSource::System,
        }
    }
}

fn to_request(settings: AudioSettings) -> Option<SettingRequest> {
    let mut request = None;
    if let Some(streams_value) = settings.streams {
        let mut streams = Vec::new();

        for stream in streams_value {
            let user_volume = stream.user_volume.unwrap();

            streams.push(AudioStream {
                stream_type: AudioStreamType::from(stream.stream.unwrap()),
                source: AudioSettingSource::from(stream.source.unwrap()),
                user_volume_level: user_volume.level.unwrap(),
                user_volume_muted: user_volume.muted.unwrap(),
            });
        }

        request = Some(SettingRequest::SetVolume(streams));
    }
    request
}

pub fn spawn_audio_fidl_handler(switchboard_client: SwitchboardClient, stream: AudioRequestStream) {
    process_stream::<AudioMarker, AudioSettings, AudioWatchResponder>(
        stream,
        switchboard_client,
        SettingType::Audio,
        Box::new(
            move |context,
                  req|
                  -> LocalBoxFuture<'_, Result<Option<AudioRequest>, anyhow::Error>> {
                async move {
                    // Support future expansion of FIDL
                    #[allow(unreachable_patterns)]
                    match req {
                        AudioRequest::Set { settings, responder } => {
                            if let Some(request) = to_request(settings) {
                                set_volume(&context.switchboard_client, request, responder).await
                            } else {
                                responder
                                    .send(&mut Err(Error::Unsupported))
                                    .log_fidl_response_error(AudioMarker::DEBUG_NAME);
                            }
                        }
                        AudioRequest::Watch { responder } => {
                            context.watch(responder).await;
                        }
                        _ => {
                            return Ok(Some(req));
                        }
                    }

                    return Ok(None);
                }
                .boxed_local()
            },
        ),
    );
}

async fn set_volume(
    switchboard_client: &SwitchboardClient,
    request: SettingRequest,
    responder: AudioSetResponder,
) {
    if let Ok(response_rx) = switchboard_client.request(SettingType::Audio, request).await {
        fasync::spawn(async move {
            // Return success if we get a Ok result from the
            // switchboard.
            if let Ok(Ok(_)) = response_rx.await {
                responder.send(&mut Ok(())).log_fidl_response_error(AudioMarker::DEBUG_NAME);
            } else {
                responder
                    .send(&mut Err(fidl_fuchsia_settings::Error::Failed))
                    .log_fidl_response_error(AudioMarker::DEBUG_NAME);
            }
        });
    } else {
        responder
            .send(&mut Err(fidl_fuchsia_settings::Error::Failed))
            .log_fidl_response_error(AudioMarker::DEBUG_NAME);
    }
}
