// Copyright 2021 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::{
        error::CallError,
        procedure::dtmf::DtmfCode,
        protocol::indicators::{CallIndicators, CallIndicatorsUpdates},
    },
    async_utils::{
        hanging_get::client::HangingGetStream,
        stream::{StreamItem, StreamMap, StreamWithEpitaph, Tagged, WithEpitaph, WithTag},
    },
    fidl::endpoints::ClientEnd,
    fidl_fuchsia_bluetooth_hfp::{CallMarker, CallProxy, PeerHandlerProxy},
    fuchsia_async as fasync,
    futures::stream::{FusedStream, Stream, StreamExt},
    log::{debug, info, warn},
    std::{
        pin::Pin,
        task::{Context, Poll},
    },
};

pub use {fidl_fuchsia_bluetooth_hfp::CallState, number::Number};

// Enclose `Number` in a submodule to keep the private items from leaking into the `calls` module.
mod number {
    use super::FidlNumber;

    /// A phone number.
    #[derive(Debug, Clone, PartialEq, Hash, Default, Eq)]
    pub struct Number(String);

    impl Number {
        /// Format value indicating no changes on the number presentation are required.
        /// See HFP v1.8, Section 4.34.2.
        const NUMBER_FORMAT: i64 = 129;

        /// Returns the numeric representation of the Number's format as specified in HFP v1.8,
        /// Section 4.34.2.
        pub fn type_(&self) -> i64 {
            Number::NUMBER_FORMAT
        }
    }

    impl From<Number> for String {
        fn from(x: Number) -> Self {
            x.0
        }
    }

    impl From<&str> for Number {
        fn from(n: &str) -> Self {
            // Phone numbers must be enclosed in double quotes
            let inner = if n.starts_with("\"") && n.ends_with("\"") {
                n.to_string()
            } else {
                format!("\"{}\"", n)
            };
            Self(inner)
        }
    }

    impl From<FidlNumber> for Number {
        fn from(n: FidlNumber) -> Self {
            n.as_str().into()
        }
    }
}

/// The index associated with a call, that is guaranteed to be unique for the lifetime of the call,
/// but will be recycled after the call is released.
pub type CallIdx = usize;

/// The direction of call initiation.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Direction {
    /// Call Direction is not known at this time.
    Unknown,
    /// Call originated on this device. This is also known as an Outgoing call.
    MobileOriginated,
    /// Call is terminated on this device. This is also known as an Incoming call.
    MobileTerminated,
}

impl From<CallState> for Direction {
    fn from(x: CallState) -> Self {
        match x {
            CallState::IncomingRinging | CallState::IncomingWaiting => Self::MobileTerminated,
            CallState::OutgoingDialing | CallState::OutgoingAlerting => Self::MobileOriginated,
            _ => Self::Unknown,
        }
    }
}

impl From<Direction> for i64 {
    fn from(x: Direction) -> Self {
        match x {
            // When we do not know the direction, arbitrarily choose Mobile Originated.
            // TODO (fxbug.dev/73326): Update the FIDL API so that the direction is always provided.
            Direction::Unknown => 0,
            Direction::MobileOriginated => 0,
            Direction::MobileTerminated => 1,
        }
    }
}

/// Internal state and resources associated with a single call.
struct CallEntry {
    /// Proxy associated with this call.
    // TODO (fxb/64550): Remove when call requests are initiated
    #[allow(unused)]
    proxy: CallProxy,
    /// The remote party's number.
    number: Number,
    /// Current state.
    state: CallState,
    /// Time of the last update to the call's `state`.
    state_updated_at: fasync::Time,
    /// Direction of the call. If the Direction cannot be determined from the Call's CallState, it
    /// is set to `Unknown`.
    direction: Direction,
}

impl CallEntry {
    pub fn new(proxy: CallProxy, number: Number, state: CallState) -> Self {
        let state_updated_at = fasync::Time::now();
        Self { proxy, number, state, state_updated_at, direction: state.into() }
    }

    /// Update the state. Also update the direction if it is Unknown.
    /// `state_updated_at` is changed only if self.state != state.
    pub fn set_state(&mut self, state: CallState) {
        if self.direction == Direction::Unknown {
            self.direction = state.into();
        }
        if self.state != state {
            self.state_updated_at = fasync::Time::now();
            self.state = state;
        }
    }

    // TODO (fxb/64550): Remove when call requests are initiated
    #[allow(unused)]
    pub fn is_active(&self) -> bool {
        self.state == CallState::OngoingActive
    }
}

/// The current state of a call.
#[derive(Debug, Clone, PartialEq)]
pub struct Call {
    /// Unique identifier associated with a call for the lifetime of the call.
    /// Once the state is `Terminated` or `TransferredToAg` the index may be reused by another
    /// call.
    pub index: CallIdx,
    /// Remote party's number.
    pub number: Number,
    /// Current state.
    pub state: CallState,
    /// Direction of the call.
    pub direction: Direction,
}

impl Call {
    pub fn new(index: CallIdx, number: Number, state: CallState, direction: Direction) -> Self {
        Self { index, number, state, direction }
    }
}

/// The fuchsia.bluetooth.hfp library representation of a Number.
type FidlNumber = String;

/// A stream of updates to the state of calls. Each update contains the `Number` and the
/// `CallState`. When the channel for a given call is closed, an epitaph is returned with the
/// `Number`.
/// The `Number` uniquely identifies a call. TODO (fxbug.dev/64558): Handle multi-party calls.
type CallStateUpdates =
    StreamMap<CallIdx, StreamWithEpitaph<Tagged<CallIdx, HangingGetStream<CallState>>, CallIdx>>;

/// Manages the state of all ongoing calls reported by the call manager.
///
/// ### Fetching Call information.
///
/// `Calls` provides methods for interacting with specific calls or listing all calls. These methods
/// can be used to query information about a call such as the associated `Number` or the
/// `CallState`.
///
///
/// ### Requesting Action on Calls
///
/// `Calls` can be used to request that a new call be made or for a call's state to be changed. Any
/// request to change the state of a call cannot be handled directly by `Calls`. Instead the request
/// will be forwarded to the Call Manager service for handling.
///
/// The state of a call is not updated to reflect a request until the Call Manager notifies `Calls`
/// that a change has taken effect. A client of `Calls` cannot assume that a request succeeded
/// until the status has been updated in `Calls`.
///
///
/// ### Calls as Stream of Call Status Updates.
///
/// Clients that are interested in changes to Call Status Updates should poll `Calls`' Stream
/// implementation. A Vec of `Indicator`s will be produced as a stream item whenever the status
/// of at least one call related `Indicator` has changed since the last stream item was produced.
///
/// The returned Vec has both Ordering and Uniqueness guarantees.
///
/// It is guaranteed to be ordered such that Indicator::Call values come before Indicator::CallSetup
/// values and Indicator::CallSetup values come before Indicator::CallHeld values.
///
/// This Vec is also is guaranteed to have no more than one value for each `Indicator` variant
/// which represents the current state of the calls as reported by the Call Manager.
pub(crate) struct Calls {
    /// A Stream of new calls.
    new_calls: Option<HangingGetStream<(ClientEnd<CallMarker>, FidlNumber, CallState)>>,
    /// Store the current state and associated resources of every Call.
    current_calls: CallList<CallEntry>,
    /// A Stream of all updates to the state of ongoing calls.
    call_updates: CallStateUpdates,
    /// The last set of indicator values returned from Polling Calls as a Stream.
    reported_indicators: CallIndicators,
    /// The Calls Stream terminated state.
    terminated: bool,
}

impl Calls {
    pub fn new(proxy: Option<PeerHandlerProxy>) -> Self {
        let new_calls =
            proxy.map(|proxy| HangingGetStream::new(Box::new(move || Some(proxy.wait_for_call()))));
        Self {
            new_calls,
            current_calls: CallList::default(),
            call_updates: CallStateUpdates::empty(),
            reported_indicators: CallIndicators::default(),
            terminated: false,
        }
    }

    /// Insert a new call
    fn handle_new_call(&mut self, call: ClientEnd<CallMarker>, number: Number, state: CallState) {
        let proxy = call.into_proxy().unwrap();
        let call = CallEntry::new(proxy.clone(), number.clone(), state);
        let index = self.current_calls.insert(call);
        let call_state = HangingGetStream::new(Box::new(move || Some(proxy.watch_state())));
        self.call_updates.insert(index, call_state.tagged(index).with_epitaph(index));
        self.terminated = false;
    }

    /// Check and mark this stream "terminated" if the appropriate conditions are met.
    /// Specifically, Calls is terminated if both `new_calls` and `call_updates` cannot produce any
    /// new values.
    fn check_termination_condition(&mut self) {
        self.terminated = self.new_calls.is_none() && self.call_updates.inner().is_empty();
    }

    /// Run `f`, passing the CallProxy associated with the given `number` into `f` and removing
    /// the CallProxy from the map if an error is returned by running `f`.
    fn send_call_request(
        &mut self,
        index: CallIdx,
        f: impl FnOnce(&CallProxy) -> Result<(), fidl::Error>,
    ) -> Result<(), CallError> {
        let result =
            f(&self.current_calls.get(index).ok_or(CallError::UnknownIndexError(index))?.proxy);
        if let Err(e) = result {
            if !e.is_closed() {
                warn!("Error making request on Call channel for call {:?}: {}", index, e);
            }
            self.remove_call(index);
        }
        Ok(())
    }

    /// Send a request to the call manager to place the call on hold.
    pub fn _request_hold(&mut self, index: CallIdx) -> Result<(), CallError> {
        self.send_call_request(index, |proxy| proxy.request_hold())
    }

    /// Send a request to the call manager to make the call active.
    /// Only one call can be active at a time. Before requesting the call at `index` be made
    /// active, all active calls are either terminated or placed on hold depending on
    /// `terminate_others`.
    pub fn request_active(
        &mut self,
        index: CallIdx,
        terminate_others: bool,
    ) -> Result<(), CallError> {
        let action =
            if terminate_others { CallProxy::request_terminate } else { CallProxy::request_hold };

        // Collect active_calls into a Vec to avoid double borrowing self.
        let active_calls: Vec<_> = self
            .current_calls
            .calls()
            .filter_map(|(i, call)| (i != index && call.is_active()).then(|| i))
            .collect();

        for i in active_calls {
            // Failures are ignored.
            let _ = self.send_call_request(i, action);
        }
        self.send_call_request(index, |proxy| proxy.request_active())
    }

    /// Send a request to the call manager to terminate the call.
    pub fn request_terminate(&mut self, index: CallIdx) -> Result<(), CallError> {
        self.send_call_request(index, |proxy| proxy.request_terminate())
    }

    /// Send a request to the call manager to transfer the audio of the call from the
    /// headset to the fuchsia device.
    pub fn _request_transfer_audio(&mut self, index: CallIdx) -> Result<(), CallError> {
        self.send_call_request(index, |proxy| proxy.request_transfer_audio())
    }

    /// Send a dtmf code to the call manager for active call,
    pub async fn send_dtmf_code(&mut self, _code: DtmfCode) {
        unimplemented!(
            "Sending a dtmf code can fail where other call requests cannot. \
            It must be handled separately"
        );
    }

    /// Return a Vec of the current call state for every call that `Calls` is tracking.
    pub fn current_calls(&self) -> Vec<Call> {
        self.current_calls
            .calls()
            .map(|(index, call)| Call::new(index, call.number.clone(), call.state, call.direction))
            .collect()
    }

    /// Remove all references to the call assigned to `index`.
    fn remove_call(&mut self, index: CallIdx) {
        self.call_updates.remove(&index);
        self.current_calls.remove(index);
    }

    /// Operations that act on calls in a particular state should act on the call that was put into
    /// that state first. `oldest_by_state` allows querying for a call that meets that criteria.
    fn oldest_by_state(&self, state: CallState) -> Option<(CallIdx, &CallEntry)> {
        self.calls().filter(|c| c.1.state == state).min_by_key(|c| c.1.state_updated_at)
    }

    /// Return the Call that has been in the IncomingRinging call state the longest if at least one
    /// exists.
    pub fn ringing(&self) -> Option<Call> {
        self.oldest_by_state(CallState::IncomingRinging)
            .map(|(idx, call)| Call::new(idx, call.number.clone(), call.state, call.direction))
    }

    /// Get the Call that has been waiting the longest. Returns None if there are no waiting calls.
    pub fn waiting(&self) -> Option<Call> {
        self.oldest_by_state(CallState::IncomingWaiting)
            .map(|(idx, call)| Call::new(idx, call.number.clone(), call.state, call.direction))
    }

    /// Answer the call that has been in the IncomingRinging state the longest.
    /// Returns an Error if there are no calls in the IncomingRinging state.
    pub fn answer(&mut self) -> Result<(), CallError> {
        let state = CallState::IncomingRinging;
        let idx = self.oldest_by_state(state).ok_or(CallError::None(vec![state]))?.0;
        self.request_active(idx, true)
    }

    /// Terminate a call.
    ///
    /// The AT+CHUP command does not specify a particular call to be terminated. When there are
    /// multiple calls that could be terminated, the Audio Gateway must make a determination as to
    /// which call to terminate. This prioritization is based on the perceived urgency of a call in
    /// a given state.
    ///
    /// Terminate a single call based on the following policy:
    ///
    ///   * The oldest Incoming Ringing call is terminated.
    ///   * If there are no Incoming Ringing calls, the oldest Ongoing Active call is terminated.
    ///   * If there are no Ongoing Active calls, the oldest Ongoing Held call is terminated.
    ///   * If there are no calls in any of the previously specified states, return an Error.
    // If it becomes desirable for this policy to be configurable, it should be pulled out into the
    // component's configuration data.
    pub fn hang_up(&mut self) -> Result<(), CallError> {
        use CallState::*;
        let idx = self
            .oldest_by_state(IncomingRinging)
            .or_else(|| self.oldest_by_state(OngoingActive))
            .or_else(|| self.oldest_by_state(OngoingHeld))
            .ok_or(CallError::None(vec![IncomingRinging, OngoingActive, OngoingHeld]))?
            .0;
        self.request_terminate(idx)
    }

    /// Returns true if the state of any calls requires ringing.
    pub fn should_ring(&self) -> bool {
        self.calls().any(|c| c.1.state == CallState::IncomingRinging)
    }

    /// Get the current `CallIndicators` based on the state of all calls.
    pub fn indicators(&mut self) -> CallIndicators {
        let mut calls = self.calls().collect::<Vec<_>>();
        calls.sort_by_key(|c| c.1.state_updated_at);
        CallIndicators::find(calls.into_iter().rev().map(|c| c.1.state))
    }

    /// Return an iterator of the calls and associated call indices.
    fn calls(&self) -> impl Iterator<Item = (CallIdx, &CallEntry)> + Clone {
        self.current_calls.calls()
    }

    /// Helper function to poll the new_calls hanging get for any available items.
    /// Polls until there are no more items ready. Updates internal state with the
    /// available items.
    fn poll_and_consume_new_calls(&mut self, cx: &mut Context<'_>) {
        // Loop until pending or self.new_calls is set to None.
        while let Some(new_calls) = &mut self.new_calls {
            match new_calls.poll_next_unpin(cx) {
                Poll::Ready(Some(Ok((call, fidl_number, state)))) => {
                    self.handle_new_call(call, fidl_number.into(), state);
                }
                Poll::Ready(Some(Err(_e))) => self.new_calls = None,
                Poll::Ready(None) => self.new_calls = None,
                Poll::Pending => break,
            }
        }
    }

    /// Helper function to poll the call_updates collection for call state changes.
    /// Polls until there are no more updates ready. Updates internal state with
    /// available items.
    fn poll_and_consume_call_updates(&mut self, cx: &mut Context<'_>) {
        // Loop until self.call_updates is terminated or the stream is exhausted.
        while !self.call_updates.is_terminated() {
            match self.call_updates.poll_next_unpin(cx) {
                Poll::Ready(Some(item)) => match item {
                    StreamItem::Item((index, Ok(state))) => {
                        if let Some(call) = self.current_calls.get_mut(index) {
                            call.set_state(state);
                        } else {
                            self.remove_call(index);
                        }
                    }
                    StreamItem::Item((index, Err(e))) => {
                        info!("Call {} channel closed with error: {}", index, e);
                        self.remove_call(index);
                    }
                    StreamItem::Epitaph(index) => {
                        debug!("Call {} channel closed", index);
                        self.remove_call(index);
                    }
                },
                Poll::Ready(None) | Poll::Pending => break,
            }
        }
    }
}

impl Unpin for Calls {}

impl Stream for Calls {
    type Item = CallIndicatorsUpdates;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.check_termination_condition();

        if self.terminated {
            return Poll::Ready(None);
        }

        // Update the state of all new and ongoing calls.
        self.poll_and_consume_new_calls(cx);
        self.poll_and_consume_call_updates(cx);

        let previous = self.reported_indicators;
        self.reported_indicators = self.indicators();

        // Return a list of all the indicators that have changed as a result of the
        // new call state.
        let changes = self.reported_indicators.difference(previous);

        if !changes.is_empty() {
            Poll::Ready(Some(changes))
        } else {
            Poll::Pending
        }
    }
}

impl FusedStream for Calls {
    fn is_terminated(&self) -> bool {
        self.terminated
    }
}

/// A collection designed for the specific requirements of storing Calls with an associated index.
///
/// The requirements found in HFP v1.8, Section 4.34.2, "+CLCC":
///
///   * Each call is assigned a number starting at 1.
///   * Calls hold their number until they are released.
///   * New calls take the lowest available number.
///
/// Note: "Insert" is a O(n) operation in order to simplify the implementation.
/// This data structure is best suited towards small n for this reason.
struct CallList<T> {
    inner: Vec<Option<T>>,
}

impl<T> Default for CallList<T> {
    fn default() -> Self {
        Self { inner: Vec::default() }
    }
}

impl<T> CallList<T> {
    /// Insert a new value into the list, returning an index that is guaranteed to be unique until
    /// the value is removed from the list.
    fn insert(&mut self, value: T) -> CallIdx {
        let index = if let Some(index) = self.inner.iter_mut().position(|v| v.is_none()) {
            self.inner[index] = Some(value);
            index
        } else {
            self.inner.push(Some(value));
            self.inner.len() - 1
        };

        Self::to_call_index(index)
    }

    /// Retrieve a value by index. Returns `None` if the index does not point to a value.
    // TODO (fxb/64550): Remove when call requests are initiated
    #[allow(unused)]
    fn get(&self, index: CallIdx) -> Option<&T> {
        match Self::to_internal_index(index) {
            Some(index) => self.inner.get(index).map(|v| v.as_ref()).unwrap_or(None),
            None => None,
        }
    }

    /// Retrieve a mutable reference to a value by index. Returns `None` if the index does not point
    /// to a value.
    fn get_mut(&mut self, index: CallIdx) -> Option<&mut T> {
        match Self::to_internal_index(index) {
            Some(index) => self.inner.get_mut(index).map(|v| v.as_mut()).unwrap_or(None),
            None => None,
        }
    }

    /// Remove a value by index. Returns `None` if the value did not point to a value.
    fn remove(&mut self, index: CallIdx) -> Option<T> {
        match Self::to_internal_index(index) {
            Some(index) => self.inner.get_mut(index).map(|v| v.take()).unwrap_or(None),
            None => None,
        }
    }

    /// Return an iterator of the calls and associated call indices.
    fn calls(&self) -> impl Iterator<Item = (CallIdx, &T)> + Clone {
        self.inner
            .iter()
            .enumerate()
            .flat_map(|(i, entry)| entry.as_ref().map(|v| (Self::to_call_index(i), v)))
    }

    /// Convert a `CallIdx` to the internal index used to locate a call.
    ///
    /// The CallIdx for a call starts at 1 instead of 0, so the internal index must be decremented
    /// after being received by the user.
    ///
    /// Returns `None` if `index` is 0 because 0 is an invalid index.
    fn to_internal_index(index: CallIdx) -> Option<usize> {
        (index != 0).then(|| index - 1)
    }

    /// Convert the internal index for a call to the external `CallIdx`.
    /// The CallIdx for a call starts at 1 instead of 0, so the internal index must be incremented
    /// before being returned to the user.
    fn to_call_index(internal: usize) -> CallIdx {
        internal + 1
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::protocol::indicators,
        fidl_fuchsia_bluetooth_hfp::{
            CallRequest, CallRequestStream, PeerHandlerMarker, PeerHandlerRequest,
            PeerHandlerRequestStream,
        },
        fuchsia_async as fasync,
        matches::assert_matches,
    };

    #[test]
    fn number_type_in_valid_range() {
        let number = Number::from("1234567");
        // type values must be in range 128-175.
        assert!(number.type_() >= 128);
        assert!(number.type_() <= 175);
    }

    #[test]
    fn number_str_roundtrip() {
        let number = Number::from("1234567");
        assert_eq!(number.clone(), Number::from(&*String::from(number)));
    }

    #[test]
    fn call_is_active() {
        // executor must be created before fidl endpoints can be created
        let _exec = fasync::Executor::new().unwrap();
        let (proxy, _) = fidl::endpoints::create_proxy::<CallMarker>().unwrap();

        let mut call = CallEntry::new(proxy, "1".into(), CallState::IncomingRinging);

        assert!(!call.is_active());
        call.set_state(CallState::OngoingActive);
        assert!(call.is_active());
        call.set_state(CallState::Terminated);
        assert!(!call.is_active());
    }

    #[test]
    fn call_list_insert() {
        let mut list = CallList::default();
        let i1 = list.insert(1);
        assert_eq!(i1, 1, "The first value must be assigned the number 1");
        let i2 = list.insert(2);
        assert_eq!(i2, 2, "The second value is assigned the next available number");
    }

    #[test]
    fn call_list_get() {
        let mut list = CallList::default();
        let i1 = list.insert(1);
        let i2 = list.insert(2);
        assert_eq!(list.get(0), None);
        assert_eq!(list.get(i1), Some(&1));
        assert_eq!(list.get(i2), Some(&2));
        assert_eq!(list.get(3), None);
    }

    #[test]
    fn call_list_get_mut() {
        let mut list = CallList::default();
        let i1 = list.insert(1);
        let i2 = list.insert(2);
        assert_eq!(list.get_mut(i1), Some(&mut 1));
        assert_eq!(list.get_mut(i2), Some(&mut 2));
        assert_eq!(list.get_mut(3), None);
    }

    #[test]
    fn call_list_remove() {
        let mut list = CallList::default();
        let i1 = list.insert(1);
        let i2 = list.insert(2);
        let removed = list.remove(i1);
        assert!(removed.is_some());
        assert_eq!(list.get(i1), None, "The value at i1 is removed");
        assert_eq!(list.get(i2), Some(&2), "The value at i2 is untouched");
        let invalid_idx = 0;
        assert!(list.remove(invalid_idx).is_none());
    }

    #[test]
    fn call_list_remove_and_insert_behaves() {
        let mut list = CallList::default();
        let i1 = list.insert(1);
        let i2 = list.insert(2);
        let i3 = list.insert(3);
        let i4 = list.insert(4);
        list.remove(i2);
        list.remove(i1);
        list.remove(i3);
        let i5 = list.insert(5);
        assert_eq!(i5, i1, "i5 is the lowest possible index (i1) even though i1 was not the first or last index removed");
        assert_eq!(list.get(i5), Some(&5), "The value at i5 is correct");
        let i6 = list.insert(6);
        let i7 = list.insert(7);
        assert_eq!(i6, i2, "i6 takes the next available index (i2)");
        assert_eq!(i7, i3, "i7 takes the next available index (i3)");
        let i8_ = list.insert(8);
        assert_ne!(i8_, i4, "i4 is reserved, so i8_ must take a new index");
        assert_eq!(
            i8_, 5,
            "i8_ takes an index of 5 since it is the last of the 5 values to be inserted"
        );
    }

    #[test]
    fn call_list_iter_returns_all_valid_values() {
        let mut list = CallList::default();
        let i1 = list.insert(1);
        let i2 = list.insert(2);
        let i3 = list.insert(3);
        let i4 = list.insert(4);
        list.remove(i2);
        let actual: Vec<_> = list.calls().collect();
        let expected = vec![(i1, &1), (i3, &3), (i4, &4)];
        assert_eq!(actual, expected);
    }

    /// The most common test setup includes an initialized Calls instance and an ongoing call.
    /// This helper function sets up a `Calls` instance in that state and returns the associated
    /// endpoints.
    fn setup_ongoing_call() -> (Calls, PeerHandlerRequestStream, CallRequestStream, CallIdx, Number)
    {
        let (proxy, peer_stream) =
            fidl::endpoints::create_proxy_and_stream::<PeerHandlerMarker>().unwrap();
        let mut calls = Calls::new(Some(proxy));
        let (client_end, call_stream) = fidl::endpoints::create_request_stream().unwrap();
        let num = Number::from("1");
        calls.handle_new_call(client_end, num.clone(), CallState::IncomingRinging);
        let expected = CallIndicators {
            call: indicators::Call::None,
            callsetup: indicators::CallSetup::Incoming,
            callwaiting: false,
            callheld: indicators::CallHeld::None,
        };
        assert_eq!(calls.indicators(), expected);
        (calls, peer_stream, call_stream, 1, num)
    }

    #[test]
    fn calls_should_ring_succeeds() {
        let mut exec = fasync::Executor::new().unwrap();

        let (mut calls, _peer_handler, mut call_stream, _idx, _num) = setup_ongoing_call();
        assert!(calls.should_ring());

        poll_next_item(&mut exec, &mut calls);

        update_call(&mut exec, &mut call_stream, CallState::OngoingActive);
        poll_next_item(&mut exec, &mut calls);

        // Call is no longer ringing after call state has changed
        assert!(!calls.should_ring());
    }

    #[fasync::run_until_stalled(test)]
    async fn call_requests_send_requests_to_server() {
        let (mut calls, _peer_handler, mut call_stream, idx, _num) = setup_ongoing_call();

        calls._request_hold(idx).expect("valid index");
        assert_matches!(call_stream.next().await, Some(Ok(CallRequest::RequestHold { .. })));

        // Make a second call that is active
        let (client_end, mut call_stream_2) = fidl::endpoints::create_request_stream().unwrap();
        let num = "2".into();
        let _ = calls.handle_new_call(client_end, num, CallState::OngoingActive);

        // Sending a RequestActive for the first call will send a RequestTerminate for the second
        // call when `true` is passed to request_active.
        calls.request_active(idx, true).expect("valid index");
        assert_matches!(call_stream.next().await, Some(Ok(CallRequest::RequestActive { .. })));
        assert_matches!(call_stream_2.next().await, Some(Ok(CallRequest::RequestTerminate { .. })));

        // Place the first call back on hold, so that we can activate it again.
        calls._request_hold(idx).expect("valid index");
        assert_matches!(call_stream.next().await, Some(Ok(CallRequest::RequestHold { .. })));

        // Make a third call that is active
        let (client_end, mut call_stream_3) = fidl::endpoints::create_request_stream().unwrap();
        let num = "3".into();
        let _ = calls.handle_new_call(client_end, num, CallState::OngoingActive);

        // Sending a RequestActive for the first call will send a RequestHold for the third
        // call when `false` is passed to request_active.
        calls.request_active(idx, false).expect("valid index");
        assert_matches!(call_stream.next().await, Some(Ok(CallRequest::RequestActive { .. })));
        assert_matches!(call_stream_3.next().await, Some(Ok(CallRequest::RequestHold { .. })));

        calls.request_terminate(idx).expect("valid index");
        assert_matches!(call_stream.next().await, Some(Ok(CallRequest::RequestTerminate { .. })));

        calls._request_transfer_audio(idx).expect("valid index");
        assert_matches!(
            call_stream.next().await,
            Some(Ok(CallRequest::RequestTransferAudio { .. }))
        );
    }

    #[fasync::run_until_stalled(test)]
    async fn call_requests_invalid_index_return_error() {
        let (mut calls, _peer_handler, _call_stream, _idx, _num) = setup_ongoing_call();

        let invalid = 2;
        let result = calls._request_hold(invalid);
        assert_eq!(result, Err(CallError::UnknownIndexError(invalid.clone())));

        let result = calls.request_active(invalid, false);
        assert_eq!(result, Err(CallError::UnknownIndexError(invalid.clone())));

        let result = calls.request_terminate(invalid);
        assert_eq!(result, Err(CallError::UnknownIndexError(invalid.clone())));

        let result = calls._request_transfer_audio(invalid);
        assert_eq!(result, Err(CallError::UnknownIndexError(invalid.clone())));
    }

    #[fasync::run_until_stalled(test)]
    async fn call_requests_manager_closed_clears_call() {
        let (mut calls, _peer_handler, call_stream, idx, num) = setup_ongoing_call();
        drop(call_stream);

        let call =
            calls.current_calls().into_iter().find(|info| info.index == idx && info.number == num);
        assert!(call.is_some(), "Call must exist in list of calls");

        // A request made to a Call channel that is closed will remove the call entry.
        let result = calls._request_hold(idx);
        assert_eq!(result, Ok(()));

        let call =
            calls.current_calls().into_iter().find(|info| info.index == idx && info.number == num);
        assert!(call.is_none(), "Call must not exist in list of calls");
    }

    /// Make a new call, manually driving async execution.
    #[track_caller]
    fn new_call(
        exec: &mut fasync::Executor,
        stream: &mut PeerHandlerRequestStream,
        num: &str,
        state: CallState,
    ) -> CallRequestStream {
        // Get WaitForCall request.
        let responder = match exec.run_until_stalled(&mut stream.next()) {
            Poll::Ready(Some(Ok(PeerHandlerRequest::WaitForCall { responder, .. }))) => responder,
            result => panic!("Unexpected result: {:?}", result),
        };
        // Respond with a call.
        let (client, call) = fidl::endpoints::create_request_stream::<CallMarker>().unwrap();
        responder.send(client, num, state).expect("response to succeed");
        call
    }

    /// Update call state, manually driving async execution.
    #[track_caller]
    fn update_call(exec: &mut fasync::Executor, stream: &mut CallRequestStream, state: CallState) {
        // Get WatchState request for call
        let responder = match exec.run_until_stalled(&mut stream.next()) {
            Poll::Ready(Some(Ok(CallRequest::WatchState { responder, .. }))) => responder,
            result => panic!("Unexpected result: {:?}", result),
        };
        // Respond with a call state.
        responder.send(state).expect("response to succeed");
    }

    /// Assert the Calls stream is pending, manually driving async execution.
    #[track_caller]
    fn assert_poll_pending(exec: &mut fasync::Executor, calls: &mut Calls) {
        let result = exec.run_until_stalled(&mut calls.next());
        assert!(result.is_pending());
    }

    /// Return the next item from the Calls stream, manually driving async execution.
    /// Panics if the stream does not produce some item.
    #[track_caller]
    fn poll_next_item(exec: &mut fasync::Executor, calls: &mut Calls) -> CallIndicatorsUpdates {
        let result = exec.run_until_stalled(&mut calls.next());
        match result {
            Poll::Ready(Some(ind)) => ind,
            result => panic!("Unexpected result: {:?}", result),
        }
    }

    #[test]
    fn calls_stream_lifecycle() {
        // Test the Stream for items when a single call is tracked, then a second call is added,
        // when the states of those calls are modified, and finally, when both calls have been
        // removed from the stream.

        let mut exec = fasync::Executor::new().unwrap();

        let (mut calls, mut handler_stream, mut call_1, _idx_1, _num_1) = setup_ongoing_call();

        let item = poll_next_item(&mut exec, &mut calls);
        let expected = CallIndicatorsUpdates {
            callsetup: Some(indicators::CallSetup::Incoming),
            ..CallIndicatorsUpdates::default()
        };
        assert_eq!(item, expected);

        // Stream doesn't have an item ready.
        assert_poll_pending(&mut exec, &mut calls);

        let mut call_2 = new_call(&mut exec, &mut handler_stream, "2", CallState::OutgoingAlerting);

        // There are no new calls in this test so close handler stream.
        drop(handler_stream);

        // Stream has an item ready.
        let item = poll_next_item(&mut exec, &mut calls);
        // The ready item is OutgoingAlerting even though there is also an IncomingRinging call.
        // This is because the OutgoingAlerting call state was reported last.
        let expected = CallIndicatorsUpdates {
            callsetup: Some(indicators::CallSetup::OutgoingAlerting),
            ..CallIndicatorsUpdates::default()
        };
        assert_eq!(item, expected);

        // Stream doesn't have an item ready.
        assert_poll_pending(&mut exec, &mut calls);

        update_call(&mut exec, &mut call_1, CallState::OngoingActive);

        // Stream has an item ready.
        let item = poll_next_item(&mut exec, &mut calls);
        // Only indicators that have changed are returned.
        let expected = CallIndicatorsUpdates {
            call: Some(indicators::Call::Some),
            ..CallIndicatorsUpdates::default()
        };
        assert_eq!(item, expected);

        drop(call_1);

        update_call(&mut exec, &mut call_2, CallState::OngoingHeld);

        // Stream has an item ready.
        let item = poll_next_item(&mut exec, &mut calls);
        let expected = CallIndicatorsUpdates {
            callsetup: Some(indicators::CallSetup::None),
            callheld: Some(indicators::CallHeld::Held),
            ..CallIndicatorsUpdates::default()
        };
        assert_eq!(item, expected);

        drop(call_2);

        // Stream has an item ready.
        let item = poll_next_item(&mut exec, &mut calls);
        let expected = CallIndicatorsUpdates {
            call: Some(indicators::Call::None),
            callheld: Some(indicators::CallHeld::None),
            ..CallIndicatorsUpdates::default()
        };
        assert_eq!(item, expected);

        assert!(!calls.is_terminated());

        // Stream doesn't have an item ready.
        let result = exec.run_until_stalled(&mut calls.next());
        assert_matches!(result, Poll::Ready(None));
        assert!(calls.is_terminated());
    }
}
