// Copyright 2022 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 fuchsia_inspect as inspect;
use fuchsia_inspect_derive::{IValue, Unit};
use futures::future::{BoxFuture, Fuse, FusedFuture, Future};
use futures::FutureExt;
use std::fmt;
use vigil::Vigil;

use crate::{a2dp, error::ScoConnectError, sco_connector::ScoConnection};

#[derive(Debug)]
pub struct ScoActive {
    pub sco_connection: ScoConnection,
    pub _pause_token: Option<a2dp::PauseToken>,
}

impl Unit for ScoActive {
    type Data = <ScoConnection as Unit>::Data;
    fn inspect_create(&self, parent: &inspect::Node, name: impl AsRef<str>) -> Self::Data {
        self.sco_connection.inspect_create(parent, name)
    }

    fn inspect_update(&self, data: &mut Self::Data) {
        self.sco_connection.inspect_update(data)
    }
}

pub enum ScoState {
    /// No call is in progress.
    Inactive,
    /// A call has been made active, and we are negotiating codecs before setting up the SCO connection.
    /// This state prevents a race where the call has been made active but SCO not yet set up, and the peer
    /// task, seeing that the connection is not Active, attempts to set up the SCO connection a second time,
    SettingUp,
    /// The HF has closed the remote SCO connection so we are waiting for the call to be set transferred to AG.
    /// This state prevents a race where the SCO connection has been torn down but the call not yet set to inactive
    /// by the call manager, so the peer task attempts to mark the call as inactive a second time.
    TearingDown,
    /// A call is transferred to the AG and we are waiting for the HF to initiate a SCO connection.
    AwaitingRemote(BoxFuture<'static, Result<ScoConnection, ScoConnectError>>),
    /// A call is active an dso is the SCO connection.
    Active(Vigil<ScoActive>),
}

impl ScoState {
    pub fn is_active(&self) -> bool {
        match self {
            Self::Active(_) => true,
            _ => false,
        }
    }

    pub fn on_connected<'a>(
        &'a mut self,
    ) -> impl Future<Output = Result<ScoConnection, ScoConnectError>> + FusedFuture + 'a {
        match self {
            Self::AwaitingRemote(ref mut fut) => fut.fuse(),
            _ => Fuse::terminated(),
        }
    }
}

impl Default for ScoState {
    fn default() -> Self {
        Self::Inactive
    }
}

impl fmt::Debug for ScoState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ScoState::Inactive => write!(f, "Inactive"),
            ScoState::SettingUp => write!(f, "SettingUp"),
            ScoState::TearingDown => write!(f, "TearingDown"),
            ScoState::AwaitingRemote(_) => write!(f, "AwaitingRemote"),
            ScoState::Active(active) => write!(f, "Active({:?})", active),
        }
    }
}

impl std::fmt::Display for ScoState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let state = match &self {
            ScoState::Inactive => "Inactive",
            ScoState::SettingUp => "SettingUp",
            ScoState::TearingDown => "TearingDown",
            ScoState::AwaitingRemote(_) => "AwaitingRemote",
            ScoState::Active(_) => "Active",
        };
        write!(f, "{}", state)
    }
}

impl Unit for ScoState {
    type Data = inspect::Node;
    fn inspect_create(&self, parent: &inspect::Node, name: impl AsRef<str>) -> Self::Data {
        let mut node = parent.create_child(String::from(name.as_ref()));
        self.inspect_update(&mut node);
        node
    }

    fn inspect_update(&self, data: &mut Self::Data) {
        data.clear_recorded();
        data.record_string("status", &format!("{}", self));
        if let ScoState::Active(active) = &self {
            let node = active.inspect_create(data, "parameters");
            data.record(node);
        }
    }
}

pub type InspectableScoState = IValue<ScoState>;

#[cfg(test)]
mod tests {
    use super::*;

    use fidl_fuchsia_bluetooth_bredr as bredr;
    use fuchsia_inspect::assert_data_tree;
    use fuchsia_inspect_derive::WithInspect;

    #[fuchsia::test]
    async fn sco_state_inspect_tree() {
        let inspect = inspect::Inspector::new();

        let mut state =
            InspectableScoState::default().with_inspect(inspect.root(), "sco_connection").unwrap();
        // Default inspect tree.
        assert_data_tree!(inspect, root: {
            sco_connection: {
                status: "Inactive",
            }
        });

        state.iset(ScoState::SettingUp);
        assert_data_tree!(inspect, root: {
            sco_connection: {
                status: "SettingUp",
            }
        });

        state.iset(ScoState::AwaitingRemote(Box::pin(async { Err(ScoConnectError::ScoFailed) })));
        assert_data_tree!(inspect, root: {
            sco_connection: {
                status: "AwaitingRemote",
            }
        });

        let params = bredr::ScoConnectionParameters {
            parameter_set: Some(bredr::HfpParameterSet::CvsdD1),
            air_coding_format: Some(bredr::CodingFormat::Cvsd),
            air_frame_size: Some(60),
            io_bandwidth: Some(16000),
            io_coding_format: Some(bredr::CodingFormat::LinearPcm),
            io_frame_size: Some(16),
            io_pcm_data_format: Some(fidl_fuchsia_hardware_audio::SampleFormat::PcmSigned),
            io_pcm_sample_payload_msb_position: Some(1),
            path: Some(bredr::DataPath::Offload),
            ..bredr::ScoConnectionParameters::EMPTY
        };
        let (sco_proxy, _sco_stream) =
            fidl::endpoints::create_proxy_and_stream::<bredr::ScoConnectionMarker>()
                .expect("ScoConnection proxy and stream");
        let vigil = Vigil::new(ScoActive {
            sco_connection: ScoConnection::build(params, sco_proxy),
            _pause_token: None,
        });
        state.iset(ScoState::Active(vigil));
        assert_data_tree!(inspect, root: {
            sco_connection: {
                status: "Active",
                parameters: {
                    parameter_set: "CvsdD1",
                    air_coding_format: "Cvsd",
                    air_frame_size: 60u64,
                    io_bandwidth: 16000u64,
                    io_coding_format: "LinearPcm",
                    io_frame_size: 16u64,
                    io_pcm_data_format: "PcmSigned",
                    io_pcm_sample_payload_msb_position: 1u64,
                    path: "Offload",
                },
            }
        });

        state.iset(ScoState::TearingDown);
        assert_data_tree!(inspect, root: {
            sco_connection: {
                status: "TearingDown",
            }
        });
    }
}
