// 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 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 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;

const THREE_WAY_SUPPORT: &[&str] = &["0", "1", "1X", "2", "2X", "3", "4"];
// 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,
}

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()),
        }
    }

    /// 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),
            _ => 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> },
}

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,
        }
    }
}

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",
        }
        .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);
    }
}
