// 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::audio::{default_audio_info, StreamVolumeControl},
    crate::input::monitor_media_buttons,
    crate::registry::base::{Command, Context, Notifier, SettingHandler, State},
    crate::registry::device_storage::DeviceStorageFactory,
    crate::service_context::ServiceContextHandle,
    crate::switchboard::base::*,
    anyhow::Error,
    fidl_fuchsia_ui_input::MediaButtonsEvent,
    fuchsia_async as fasync,
    fuchsia_syslog::fx_log_err,
    futures::StreamExt,
    parking_lot::RwLock,
    std::collections::HashMap,
    std::sync::Arc,
};

fn get_streams_array_from_map(
    stream_map: &HashMap<AudioStreamType, StreamVolumeControl>,
) -> [AudioStream; 5] {
    let mut streams: [AudioStream; 5] = default_audio_info().streams;
    for i in 0..streams.len() {
        if let Some(volume_control) = stream_map.get(&streams[i].stream_type) {
            streams[i] = volume_control.stored_stream.clone();
        }
    }
    streams
}

/// Controller that handles commands for SettingType::Audio.
/// TODO(go/fxb/35988): Hook up the presentation service to listen for the mic mute state.
pub fn spawn_audio_controller<T: DeviceStorageFactory + Send + Sync + 'static>(
    context: &Context<T>,
) -> SettingHandler {
    let service_context_handle = context.environment.service_context_handle.clone();
    let storage_factory_handle = context.environment.storage_factory_handle.clone();
    let (audio_handler_tx, mut audio_handler_rx) = futures::channel::mpsc::unbounded::<Command>();

    let default_audio_settings = default_audio_info();

    let notifier_lock = Arc::<RwLock<Option<Notifier>>>::new(RwLock::new(None));
    let mic_mute_state =
        Arc::<RwLock<bool>>::new(RwLock::new(default_audio_settings.input.mic_mute));
    let input_service_connected = Arc::<RwLock<bool>>::new(RwLock::new(false));
    let audio_service_connected = Arc::<RwLock<bool>>::new(RwLock::new(false));

    let mut stream_volume_controls = HashMap::new();

    let (input_tx, mut input_rx) = futures::channel::mpsc::unbounded::<MediaButtonsEvent>();

    let input_service_connected_clone = input_service_connected.clone();
    let service_context_handle_clone = service_context_handle.clone();
    let input_tx_clone = input_tx.clone();

    fasync::spawn(async move {
        *input_service_connected_clone.write() =
            monitor_media_buttons(service_context_handle_clone, input_tx_clone).await.is_ok();
    });

    let mic_mute_state_clone = mic_mute_state.clone();
    let notifier_lock_clone = notifier_lock.clone();
    fasync::spawn(async move {
        while let Some(event) = input_rx.next().await {
            if let Some(mic_mute) = event.mic_mute {
                if *mic_mute_state_clone.read() != mic_mute {
                    *mic_mute_state_clone.write() = mic_mute;
                    if let Some(notifier) = (*notifier_lock_clone.read()).clone() {
                        notifier.unbounded_send(SettingType::Audio).unwrap();
                    }
                }
            }
        }
        fx_log_err!("[audio_controller] exited input event loop");
    });

    let input_service_connected_clone = input_service_connected.clone();
    let service_context_handle_clone = service_context_handle.clone();
    fasync::spawn(async move {
        check_and_bind_volume_controls(
            audio_service_connected.clone(),
            service_context_handle_clone,
            &mut stream_volume_controls,
        )
        .await
        .ok();

        let storage = storage_factory_handle.lock().await.get_store::<AudioInfo>();
        let mut changed_streams = None;

        while let Some(command) = audio_handler_rx.next().await {
            match command {
                Command::ChangeState(state) => match state {
                    State::Listen(notifier) => {
                        *notifier_lock.write() = Some(notifier);
                    }
                    State::EndListen => {
                        *notifier_lock.write() = None;
                    }
                },
                Command::HandleRequest(request, responder) => {
                    let mut stored_value = storage.lock().await.get().await;

                    #[allow(unreachable_patterns)]
                    match request {
                        SettingRequest::Restore => {
                            let stored_streams = stored_value.streams.iter().cloned().collect();
                            update_volume_stream(&stored_streams, &mut stream_volume_controls)
                                .await;
                        }
                        SettingRequest::SetVolume(volume) => {
                            if check_and_bind_volume_controls(
                                audio_service_connected.clone(),
                                service_context_handle.clone(),
                                &mut stream_volume_controls,
                            )
                            .await
                            .is_err()
                            {
                                continue;
                            };
                            update_volume_stream(&volume, &mut stream_volume_controls).await;
                            changed_streams = Some(volume);
                            stored_value.streams =
                                get_streams_array_from_map(&stream_volume_controls);

                            let storage_handle_clone = storage.clone();
                            fasync::spawn(async move {
                                let mut storage_lock = storage_handle_clone.lock().await;
                                storage_lock.write(&stored_value, false).await.unwrap_or_else(
                                    move |e| {
                                        fx_log_err!("failed storing audio, {}", e);
                                    },
                                );
                            });
                            let _ = responder.send(Ok(None)).ok();
                            if let Some(notifier) = (*notifier_lock.read()).clone() {
                                notifier.unbounded_send(SettingType::Audio).unwrap();
                            }
                        }
                        SettingRequest::Get => {
                            {
                                if !*input_service_connected_clone.read() {
                                    let connected = monitor_media_buttons(
                                        service_context_handle.clone(),
                                        input_tx.clone(),
                                    )
                                    .await
                                    .is_ok();

                                    *input_service_connected_clone.write() = connected;
                                }
                            }

                            check_and_bind_volume_controls(
                                audio_service_connected.clone(),
                                service_context_handle.clone(),
                                &mut stream_volume_controls,
                            )
                            .await
                            .ok();
                            let _ = responder
                                .send(Ok(Some(SettingResponse::Audio(AudioInfo {
                                    streams: stored_value.streams,
                                    input: AudioInputInfo { mic_mute: *mic_mute_state.read() },
                                    changed_streams: changed_streams.clone(),
                                }))))
                                .ok();
                        }
                        _ => {
                            responder
                                .send(Err(SwitchboardError::UnimplementedRequest {
                                    setting_type: SettingType::Audio,
                                    request: request,
                                }))
                                .ok();
                        }
                    }
                }
            }
        }
        fx_log_err!("[audio_controller] exited service event loop");
    });
    audio_handler_tx
}

// Updates |stored_audio_streams| and then update volume via the AudioCore service.
async fn update_volume_stream(
    new_streams: &Vec<AudioStream>,
    stored_volume_controls: &mut HashMap<AudioStreamType, StreamVolumeControl>,
) {
    for stream in new_streams {
        if let Some(volume_control) = stored_volume_controls.get_mut(&stream.stream_type) {
            volume_control.set_volume(stream.clone()).await;
        }
    }
}

// Checks to see if |service_connected| contains true. If it is not, then
// connect to the audio core service. If the service connects successfully,
// set |service_connected| to true and create a StreamVolumeControl for each
// stream type.
async fn check_and_bind_volume_controls(
    service_connected: Arc<RwLock<bool>>,
    service_context_handle: ServiceContextHandle,
    stream_volume_controls: &mut HashMap<AudioStreamType, StreamVolumeControl>,
) -> Result<(), Error> {
    if *service_connected.read() {
        return Ok(());
    }

    let service_result =
        service_context_handle.lock().await.connect::<fidl_fuchsia_media::AudioCoreMarker>().await;

    let audio_service = match service_result {
        Ok(service) => {
            *service_connected.write() = true;
            service
        }
        Err(err) => {
            fx_log_err!("failed to connect to audio core, {}", err);
            return Err(err);
        }
    };

    for stream in default_audio_info().streams.iter() {
        stream_volume_controls.insert(
            stream.stream_type.clone(),
            StreamVolumeControl::create(&audio_service, stream.clone()),
        );
    }
    Ok(())
}
