// 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 {
    at_commands as at,
    std::{fmt, iter::once},
    thiserror::Error,
};

use crate::{
    peer::{
        calls::Call,
        gain_control::Gain,
        service_level_connection::{Command, SlcState},
    },
    protocol::{
        features::AgFeatures,
        indicators::{AgIndicator, AgIndicators, HfIndicator, HfIndicators},
    },
};

/// Defines the implementation of the Answer Procedure.
pub mod answer;

/// Defines the implementation of the DTMF Procedure.
pub mod dtmf;

/// Defines the implementation of the Call Waiting Notifications Procedure.
pub mod call_waiting_notifications;

/// Defines the implementation of the Call Line Identification Notifications Procedure.
pub mod call_line_ident_notifications;

/// Defines the implementation of the Report Extended Audio Gateway Error Code Results Procedure.
pub mod extended_errors;

/// Defines the implementation of the Hang Up Procedure.
pub mod hang_up;

/// Defines the implementation of the Hold Procedure.
pub mod hold;

/// Defines the implementation of the SLC Initialization Procedure.
pub mod slc_initialization;

/// Defines the implementation of the Subscriber Number Information Procedure.
pub mod subscriber_number_information;

/// Defines the implementation of the NR/EC Procedure.
pub mod nrec;

/// Defines the implementation of the Query List of Current Calls Procedure.
pub mod query_current_calls;

/// Defines the implementation of the Indicators Activation and Deactivation Procedure.
pub mod indicators_activation;

/// Defines the implementation of the Query Operator Selection Procedure.
pub mod query_operator_selection;

/// Defines the implementation of the Ring Procedure.
pub mod ring;

/// Defines the implementation of the Phone Status Procedures.
pub mod phone_status;

/// Defines the implementation of the Transfer of HF Indicator Values Procedure.
pub mod transfer_hf_indicator;

/// Defines the implementation of the Volume Level Synchronization Procedure.
pub mod volume_synchronization;

use answer::AnswerProcedure;
use call_line_ident_notifications::CallLineIdentNotificationsProcedure;
use call_waiting_notifications::CallWaitingNotificationsProcedure;
use dtmf::{DtmfCode, DtmfProcedure};
use extended_errors::ExtendedErrorsProcedure;
use hang_up::HangUpProcedure;
use hold::{CallHoldAction, HoldProcedure};
use indicators_activation::IndicatorsActivationProcedure;
use nrec::NrecProcedure;
use phone_status::PhoneStatusProcedure;
use query_current_calls::{build_clcc_response, QueryCurrentCallsProcedure};
use query_operator_selection::QueryOperatorProcedure;
use ring::RingProcedure;
use slc_initialization::SlcInitProcedure;
use subscriber_number_information::{build_cnum_response, SubscriberNumberInformationProcedure};
use transfer_hf_indicator::TransferHfIndicatorProcedure;
use volume_synchronization::VolumeSynchronizationProcedure;

// TODO (fxbug.dev/74091): Add multiparty support.
// TODO (fxbug.dev/74093): Add Explicit Call Transfer support.
const THREE_WAY_SUPPORT: &[&str] = &["0", "1", "1X", "2", "2X"];

// TODO(fxb/71668) Stop using raw bytes.
const CIND_TEST_RESPONSE_BYTES: &[u8] = b"+CIND: \
(\"service\",(0,1)),\
(\"call\",(0,1)),\
(\"callsetup\",(0,3)),\
(\"callheld\",(0,2)),\
(\"signal\",(0,5)),\
(\"roam\",(0,1)),\
(\"battchg\",(0,5)\
)";

// TODO (fxbug.dev/72873): Replace with defined AT RING repsonse.
const RING_BYTES: &[u8] = b"RING";

/// Errors that can occur during the operation of an HFP Procedure.
#[derive(Clone, Error, Debug)]
pub enum ProcedureError {
    #[error("Unexpected AG procedural update: {:?}", .0)]
    UnexpectedAg(AgUpdate),
    #[error("Unparsable HF procedural update: {:?}", .0)]
    UnparsableHf(at::DeserializeError),
    #[error("Unexpected HF procedural update: {:?}", .0)]
    UnexpectedHf(at::Command),
    #[error("Invalid HF argument in procedural update: {:?}", .0)]
    InvalidHfArgument(at::Command),
    #[error("Unexpected procedure request")]
    UnexpectedRequest,
    #[error("Procedure has already terminated")]
    AlreadyTerminated,
    #[error("Procedure not implemented")]
    NotImplemented,
    #[error("Error in the underlying service level connection: {:?}", .0)]
    Channel(fuchsia_zircon::Status),
}

impl From<fuchsia_zircon::Status> for ProcedureError {
    fn from(src: fuchsia_zircon::Status) -> Self {
        ProcedureError::Channel(src)
    }
}

impl From<&Command> for ProcedureError {
    fn from(src: &Command) -> Self {
        match src {
            Command::Ag(cmd) => Self::UnexpectedAg(cmd.clone()),
            Command::Hf(cmd) => Self::UnexpectedHf(cmd.clone()),
        }
    }
}

impl From<&at::Command> for ProcedureError {
    fn from(src: &at::Command) -> Self {
        Self::UnexpectedHf(src.clone())
    }
}

/// A unique identifier associated with an HFP procedure.
// TODO(fxbug.dev/70591): Add to this enum as more procedures are implemented.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum ProcedureMarker {
    /// The Service Level Connection Initialization procedure as defined in HFP v1.8 Section 4.2.
    SlcInitialization,
    /// The Transmit DTMF Code procedure as defined in HFP v1.8 Section 4.28.
    Dtmf,
    /// The Noise Reduction/Echo Cancelation procedure as defined in HFP v1.8 Section 4.24.
    Nrec,
    /// The Query Operator Selection procedure as defined in HFP v1.8 Section 4.8.
    QueryOperatorSelection,
    /// The Extended Audio Gateway Error Results Code as defined in HFP v1.8 Section 4.9.
    ExtendedErrors,
    /// The Extended Audio Gateway Error Results Code as defined in HFP v1.8 Section 4.21.
    CallWaitingNotifications,
    /// The Call Line Identification Notifications as defined in HFP v1.8 Section 4.23.
    CallLineIdentNotifications,
    /// The Transfer of Phone Status procedures as defined in HFP v1.8 Section 4.4 - 4.7.
    PhoneStatus,
    /// The Subscriber Number Information procedure as defined in HFP v1.8 Section 4.31.
    SubscriberNumberInformation,
    /// The Volume Level Synchronization procedure as defined in HFP v1.8 Section 4.29.2.
    VolumeSynchronization,
    /// The Query List of Current Calls procedure as defined in HFP v1.8 Section 4.32.1.
    QueryCurrentCalls,
    /// The Indicators Activation and Deactivation procedure as defined in HFP v1.8 Section 4.35.
    Indicators,
    /// The Ring procedure as defined in HFP v1.8 Section 4.13
    Ring,
    /// The Answer procedure as defined in HFP v1.8 Section 4.13
    Answer,
    /// The Hang Up procedure as defined in HFP v1.8 Sections 4.14 - 4.15
    HangUp,
    /// The Transfer of HF Indicator Values procedure as defined in HFP v1.8 Section 4.36.1.5.
    TransferHfIndicator,
    /// The Call Hold procedure as defined in HFP v1.8 Section 4.22
    Hold,
}

impl ProcedureMarker {
    /// Initializes a new procedure for the current marker.
    pub fn initialize(&self) -> Box<dyn Procedure> {
        match self {
            Self::SlcInitialization => Box::new(SlcInitProcedure::new()),
            Self::Nrec => Box::new(NrecProcedure::new()),
            Self::QueryOperatorSelection => Box::new(QueryOperatorProcedure::new()),
            Self::ExtendedErrors => Box::new(ExtendedErrorsProcedure::new()),
            Self::CallWaitingNotifications => Box::new(CallWaitingNotificationsProcedure::new()),
            Self::CallLineIdentNotifications => {
                Box::new(CallLineIdentNotificationsProcedure::new())
            }
            Self::PhoneStatus => Box::new(PhoneStatusProcedure::new()),
            Self::SubscriberNumberInformation => {
                Box::new(SubscriberNumberInformationProcedure::new())
            }
            Self::Dtmf => Box::new(DtmfProcedure::new()),
            Self::VolumeSynchronization => Box::new(VolumeSynchronizationProcedure::new()),
            Self::QueryCurrentCalls => Box::new(QueryCurrentCallsProcedure::new()),
            Self::Indicators => Box::new(IndicatorsActivationProcedure::new()),
            Self::Ring => Box::new(RingProcedure::new()),
            Self::Answer => Box::new(AnswerProcedure::new()),
            Self::HangUp => Box::new(HangUpProcedure::new()),
            Self::TransferHfIndicator => Box::new(TransferHfIndicatorProcedure::new()),
            Self::Hold => Box::new(HoldProcedure::new()),
        }
    }

    /// Matches the HF `command` to a procedure. `initialized` represents the initialization state
    /// of the Service Level Connection.
    ///
    /// Returns an error if the command is unable to be matched.
    pub fn match_command(command: &at::Command, initialized: bool) -> Result<Self, ProcedureError> {
        match command {
            at::Command::Brsf { .. }
            | at::Command::Bac { .. }
            | at::Command::CindTest { .. }
            | at::Command::CindRead { .. }
            | at::Command::ChldTest { .. }
            | at::Command::BindTest { .. }
            | at::Command::BindRead { .. } => Ok(Self::SlcInitialization),
            at::Command::Cmer { .. } if initialized => Ok(Self::Indicators),
            at::Command::Cmer { .. } => Ok(Self::SlcInitialization),
            at::Command::Nrec { .. } => Ok(Self::Nrec),
            at::Command::Cops { .. } | at::Command::CopsRead { .. } => {
                Ok(Self::QueryOperatorSelection)
            }
            at::Command::Cmee { .. } => Ok(Self::ExtendedErrors),
            at::Command::Ccwa { .. } => Ok(Self::CallWaitingNotifications),
            at::Command::Clcc { .. } => Ok(Self::QueryCurrentCalls),
            at::Command::Clip { .. } => Ok(Self::CallLineIdentNotifications),
            at::Command::Cnum { .. } => Ok(Self::SubscriberNumberInformation),
            at::Command::Vgs { .. } | at::Command::Vgm { .. } => Ok(Self::VolumeSynchronization),
            at::Command::Vts { .. } => Ok(Self::Dtmf),
            at::Command::Answer { .. } => Ok(Self::Answer),
            at::Command::Chup { .. } => Ok(Self::HangUp),
            at::Command::Biev { .. } => Ok(Self::TransferHfIndicator),
            at::Command::Bia { .. } => Ok(Self::Indicators),
            at::Command::Chld { .. } => Ok(Self::Hold),
            _ => Err(ProcedureError::NotImplemented),
        }
    }
}

/// Information requests - use the `response` fn to build a response to the request.
// TODO(fxbug.dev/70591): Add to this list once more procedures are implemented.
pub enum InformationRequest {
    GetAgFeatures { response: Box<dyn FnOnce(AgFeatures) -> AgUpdate> },

    GetAgIndicatorStatus { response: Box<dyn FnOnce(AgIndicators) -> AgUpdate> },

    GetNetworkOperatorName { response: Box<dyn FnOnce(Option<String>) -> AgUpdate> },

    GetSubscriberNumberInformation { response: Box<dyn FnOnce(Vec<String>) -> AgUpdate> },

    SetNrec { enable: bool, response: Box<dyn FnOnce(Result<(), ()>) -> AgUpdate> },

    SendHfIndicator { indicator: HfIndicator, response: Box<dyn FnOnce() -> AgUpdate> },

    SendDtmf { code: DtmfCode, response: Box<dyn FnOnce() -> AgUpdate> },

    SpeakerVolumeSynchronization { level: Gain, response: Box<dyn FnOnce() -> AgUpdate> },

    MicrophoneVolumeSynchronization { level: Gain, response: Box<dyn FnOnce() -> AgUpdate> },

    QueryCurrentCalls { response: Box<dyn FnOnce(Vec<Call>) -> AgUpdate> },

    Answer { response: Box<dyn FnOnce(Result<(), ()>) -> AgUpdate> },

    HangUp { response: Box<dyn FnOnce(Result<(), ()>) -> AgUpdate> },

    Hold { command: CallHoldAction, response: Box<dyn FnOnce(Result<(), ()>) -> AgUpdate> },
}

impl From<&InformationRequest> for ProcedureMarker {
    fn from(src: &InformationRequest) -> ProcedureMarker {
        use InformationRequest::*;
        match src {
            GetAgFeatures { .. } | GetAgIndicatorStatus { .. } => Self::SlcInitialization,
            GetNetworkOperatorName { .. } => Self::QueryOperatorSelection,
            GetSubscriberNumberInformation { .. } => Self::SubscriberNumberInformation,
            SetNrec { .. } => Self::Nrec,
            SendDtmf { .. } => Self::Dtmf,
            SendHfIndicator { .. } => Self::TransferHfIndicator,
            SpeakerVolumeSynchronization { .. } | MicrophoneVolumeSynchronization { .. } => {
                Self::VolumeSynchronization
            }
            QueryCurrentCalls { .. } => Self::QueryCurrentCalls,
            Answer { .. } => Self::Answer,
            HangUp { .. } => Self::HangUp,
            Hold { .. } => Self::Hold,
        }
    }
}

impl fmt::Debug for InformationRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s;
        let output = match &self {
            Self::GetAgFeatures { .. } => "GetAgFeatures",
            Self::GetAgIndicatorStatus { .. } => "GetAgIndicatorStatus",
            Self::GetSubscriberNumberInformation { .. } => "GetSubscriberNumberInformation",
            Self::SetNrec { enable: true, .. } => "SetNrec(enabled)",
            Self::SetNrec { enable: false, .. } => "SetNrec(disabled)",
            Self::GetNetworkOperatorName { .. } => "GetNetworkOperatorName",
            Self::QueryCurrentCalls { .. } => "QueryCurrentCalls ",
            // DTFM Code values are not displayed in Debug representation
            Self::SendDtmf { .. } => "SendDtmf",
            Self::SendHfIndicator { indicator, .. } => {
                s = format!("SendHfIndicator({:?})", indicator);
                &s
            }
            Self::SpeakerVolumeSynchronization { level, .. } => {
                s = format!("SpeakerVolumeSynchronization({:?})", level);
                &s
            }
            Self::MicrophoneVolumeSynchronization { level, .. } => {
                s = format!("MicrophoneVolumeSynchronization({:?})", level);
                &s
            }
            Self::Answer { .. } => "Answer",
            Self::HangUp { .. } => "HangUp",
            Self::Hold { .. } => "Hold",
        }
        .to_string();
        write!(f, "{}", output)
    }
}

/// The requests generated by an HFP procedure as it progresses through its state machine.
#[derive(Debug)]
pub enum ProcedureRequest {
    /// AT messages to be sent to the peer (HF) - requires no response.
    SendMessages(Vec<at::Response>),

    /// Request for information from the HFP component.
    Info(InformationRequest),

    /// Error from processing an update.
    Error(ProcedureError),

    /// No-op.
    None,
}

impl ProcedureRequest {
    /// Returns true if this request requires a response.
    pub fn requires_response(&self) -> bool {
        match &self {
            Self::Info(..) => true,
            _ => false,
        }
    }
}

impl From<Vec<at::Response>> for ProcedureRequest {
    fn from(messages: Vec<at::Response>) -> Self {
        Self::SendMessages(messages)
    }
}

impl From<InformationRequest> for ProcedureRequest {
    fn from(src: InformationRequest) -> Self {
        Self::Info(src)
    }
}

impl From<ProcedureError> for ProcedureRequest {
    fn from(src: ProcedureError) -> Self {
        Self::Error(src)
    }
}

/// An interface to interact with an HFP Procedure.
pub trait Procedure {
    /// Returns the unique identifier associated with this procedure.
    fn marker(&self) -> ProcedureMarker;

    /// Receive an HF `update` to progress the procedure. Returns a request
    /// to the update.
    ///
    /// `update` is the incoming AT message received from the HF.
    /// `state` is the shared state associated with the service level connection and may be
    /// modified when applying the update.
    ///
    /// There are no guarantees if `hf_update()` is called on a Procedure that is terminated
    /// (namely, `is_terminated()` returns true) and may result in an error request.
    /// The handling of unexpected or invalid updates is procedure dependent.
    ///
    /// Developers should ensure that the final request of a Procedure does not require
    /// a response.
    fn hf_update(&mut self, update: at::Command, _state: &mut SlcState) -> ProcedureRequest {
        ProcedureRequest::Error(ProcedureError::UnexpectedHf(update))
    }

    /// Receive an AG `update` to progress the procedure. Returns a request
    /// to the update.
    ///
    /// `update` is the incoming AT message received from the AG.
    /// `state` is the shared state associated with the service level connection and may be
    /// modified when applying the update.
    ///
    /// There are no guarantees if `ag_update()` is called on a Procedure that is terminated
    /// (namely, `is_terminated()` returns true) and may result in an error request.
    /// The handling of unexpected or invalid updates is procedure dependent.
    ///
    /// Developers should ensure that the final request of a Procedure does not require
    /// a response.
    fn ag_update(&mut self, update: AgUpdate, _state: &mut SlcState) -> ProcedureRequest {
        ProcedureRequest::Error(ProcedureError::UnexpectedAg(update))
    }

    /// Returns true if the Procedure is finished.
    fn is_terminated(&self) -> bool {
        false
    }
}

/// An update from the AG. Each update contains all the information necessary to generate a list of
/// AT responses.
#[derive(Debug, Clone)]
pub enum AgUpdate {
    /// HFP Features supported by the AG
    Features(AgFeatures),
    /// Three Way Calling support
    ThreeWaySupport,
    /// Current status of all AG Indicators
    IndicatorStatus(AgIndicators),
    /// An Update that contains no additional information
    Ok,
    /// An error occurred and should be communicated to the HF
    Error,
    /// Supported AG Indicators
    SupportedAgIndicators,
    /// The AG's supported HF indicators.
    SupportedHfIndicators { safety: bool, battery: bool },
    /// The current status (enabled/disabled) of the AG's supported HF indicators.
    SupportedHfIndicatorStatus(HfIndicators),
    /// The name of the network operator
    NetworkOperatorName(at::NetworkOperatorNameFormat, String),
    /// Phone status indicator
    PhoneStatusIndicator(AgIndicator),
    /// The AG's network subscriber number(s).
    SubscriberNumbers(Vec<String>),
    /// The list of ongoing calls.
    CurrentCalls(Vec<Call>),
    /// The information of an IncomingRinging call.
    Ring(Call),
    /// The information of an IncomingRinging call.
    CallWaiting(Call),
}

impl From<AgUpdate> for ProcedureRequest {
    fn from(msg: AgUpdate) -> Self {
        match msg {
            AgUpdate::Features(features) => vec![
                at::success(at::Success::Brsf { features: features.bits() as i64 }),
                at::Response::Ok,
            ],
            AgUpdate::ThreeWaySupport => {
                let commands = THREE_WAY_SUPPORT.into_iter().map(|&s| s.into()).collect();
                vec![at::success(at::Success::Chld { commands }), at::Response::Ok]
            }
            AgUpdate::IndicatorStatus(status) => vec![
                at::success(at::Success::Cind {
                    service: status.service,
                    call: status.call.into(),
                    callsetup: status.callsetup as i64,
                    callheld: status.callheld as i64,
                    signal: status.signal as i64,
                    roam: status.roam,
                    battchg: status.battchg as i64,
                }),
                at::Response::Ok,
            ],
            AgUpdate::Ok => vec![at::Response::Ok],
            AgUpdate::Error => vec![at::Response::Error],
            AgUpdate::SupportedAgIndicators => {
                vec![at::Response::RawBytes(CIND_TEST_RESPONSE_BYTES.to_vec()), at::Response::Ok]
            }
            AgUpdate::SupportedHfIndicators { safety, battery } => {
                let mut indicators = vec![];
                if safety {
                    indicators.push(at::BluetoothHFIndicator::EnhancedSafety);
                }
                if battery {
                    indicators.push(at::BluetoothHFIndicator::BatteryLevel);
                }
                vec![at::success(at::Success::BindList { indicators }), at::Response::Ok]
            }
            AgUpdate::SupportedHfIndicatorStatus(hf_indicators) => hf_indicators.bind_response(),
            AgUpdate::NetworkOperatorName(format, name) => vec![
                at::success(at::Success::Cops {
                    format,
                    zero: 0,
                    // TODO(fxbug.dev/72112) Make this optional if it's not set.
                    operator: name,
                }),
                at::Response::Ok,
            ],
            AgUpdate::PhoneStatusIndicator(status) => {
                vec![status.into()]
            }
            AgUpdate::SubscriberNumbers(numbers) => {
                numbers.into_iter().map(build_cnum_response).chain(once(at::Response::Ok)).collect()
            }
            AgUpdate::CurrentCalls(calls) => calls
                .into_iter()
                .filter_map(build_clcc_response)
                .chain(once(at::Response::Ok))
                .collect(),
            AgUpdate::Ring(call) => {
                vec![
                    at::Response::RawBytes(RING_BYTES.to_vec()),
                    at::success(at::Success::Clip {
                        ty: call.number.type_(),
                        number: call.number.into(),
                    }),
                ]
            }
            AgUpdate::CallWaiting(call) => {
                vec![at::success(at::Success::Ccwa {
                    ty: call.number.type_(),
                    number: call.number.into(),
                })]
            }
        }
        .into()
    }
}

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

    /// A vec of responses converts to the expected request
    #[test]
    fn at_responses_to_procedure_request_conversion() {
        let messages = vec![at::Response::Ok, at::Response::Error];
        let request: ProcedureRequest = messages.into();
        assert_matches!(
            request,
            ProcedureRequest::SendMessages(messages)
                if messages == vec![at::Response::Ok, at::Response::Error]
        );
    }

    #[test]
    fn match_conditional_commands_based_on_slci() {
        let command = at::Command::Cmer { mode: 3, keyp: 0, disp: 0, ind: 1 };
        let marker = ProcedureMarker::match_command(&command, false).expect("command to match");
        assert_eq!(marker, ProcedureMarker::SlcInitialization);

        let command = at::Command::Cmer { mode: 3, keyp: 0, disp: 0, ind: 1 };
        let marker = ProcedureMarker::match_command(&command, true).expect("command to match");
        assert_eq!(marker, ProcedureMarker::Indicators);
    }
}
