#!/usr/bin/env python3
#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""
Test the HFP profile for basic calling functionality.
"""

import time
from acts.test_decorators import test_tracker_info
from acts_contrib.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
from acts_contrib.test_utils.bt.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest
from acts_contrib.test_utils.bt import BtEnum
from acts_contrib.test_utils.bt import bt_test_utils
from acts_contrib.test_utils.car import car_telecom_utils
from acts_contrib.test_utils.car import tel_telecom_utils
from acts_contrib.test_utils.tel import tel_defines

BLUETOOTH_PKG_NAME = "com.android.bluetooth"
CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING"
CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING"
AUDIO_STATE_DISCONNECTED = 0
AUDIO_STATE_ROUTED = 2
SHORT_TIMEOUT = 5


class BtCarHfpTest(BluetoothCarHfpBaseTest):
    def setup_class(self):
        if not super(BtCarHfpTest, self).setup_class():
            return False
        # Disable the A2DP profile.
        bt_test_utils.set_profile_priority(self.hf, self.ag, [
            BtEnum.BluetoothProfile.PBAP_CLIENT.value,
            BtEnum.BluetoothProfile.A2DP_SINK.value
        ], BtEnum.BluetoothPriorityLevel.PRIORITY_OFF)
        bt_test_utils.set_profile_priority(
            self.hf, self.ag, [BtEnum.BluetoothProfile.HEADSET_CLIENT.value],
            BtEnum.BluetoothPriorityLevel.PRIORITY_ON)

        if not bt_test_utils.connect_pri_to_sec(
                self.hf, self.ag,
                set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])):
            self.log.error("Failed to connect.")
            return False
        return True

    @test_tracker_info(uuid='4ce2195a-b70a-4584-912e-cbd20d20e19d')
    @BluetoothBaseTest.bt_test_wrap
    def test_default_calling_account(self):
        """
        Tests if the default calling account is coming from the
        bluetooth pacakge.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Check if the default calling account is via Bluetooth package.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        selected_acc = \
            self.hf.droid.telecomGetUserSelectedOutgoingPhoneAccount()
        if not selected_acc:
            self.hf.log.error("No default account found.")
            return False

        # Check if the default account is from the Bluetooth package. This is a
        # light weight check.
        try:
            acc_component_id = selected_acc['ComponentName']
        except KeyError:
            self.hf.log.error("No component name for account {}".format(
                selected_acc))
            return False
        if not acc_component_id.startswith(BLUETOOTH_PKG_NAME):
            self.hf.log.error("Component name does not start with pkg name {}".
                              format(selected_acc))
            return False
        return True

    @test_tracker_info(uuid='e579009d-05f3-4236-a698-5de8c11d73a9')
    @BluetoothBaseTest.bt_test_wrap
    def test_outgoing_call_hf(self):
        """
        Tests if we can make a phone call from HF role and disconnect from HF
        role.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Make a call from HF role.
        2. Wait for the HF, AG to be dialing and RE to see the call ringing.
        3. Hangup the call on HF role.
        4. Wait for all devices to hangup the call.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        return self.dial_a_hangup_b(self.hf, self.hf)

    @test_tracker_info(uuid='c9d5f9cd-f275-4adf-b212-c2e9a70d4cac')
    @BluetoothBaseTest.bt_test_wrap
    def test_outgoing_call_ag(self):
        """
        Tests if we can make a phone call from AG role and disconnect from AG
        role.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Make a call from AG role.
        2. Wait for the HF, AG to be in dialing and RE to see the call ringing.
        3. Hangup the call on AG role.
        4. Wait for all devices to hangup the call.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        return self.dial_a_hangup_b(self.ag, self.ag)

    @test_tracker_info(uuid='908c199b-ca65-4694-821d-1b864ee3fe69')
    @BluetoothBaseTest.bt_test_wrap
    def test_outgoing_dial_ag_hangup_hf(self):
        """
        Tests if we can make a phone call from AG role and disconnect from HF
        role.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Make a call from AG role.
        2. Wait for the HF, AG to show dialing and RE to see the call ringing.
        3. Hangup the call on HF role.
        4. Wait for all devices to hangup the call.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        return self.dial_a_hangup_b(self.ag, self.hf)

    @test_tracker_info(uuid='5d1d52c7-51d8-4c82-b437-2e91a6220db3')
    @BluetoothBaseTest.bt_test_wrap
    def test_outgoing_dial_hf_hangup_ag(self):
        """
        Tests if we can make a phone call from HF role and disconnect from AG
        role.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Make a call from HF role.
        2. Wait for the HF, AG to show dialing and RE to see the call ringing.
        3. Hangup the call on AG role.
        4. Wait for all devices to hangup the call.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        return self.dial_a_hangup_b(self.hf, self.ag)

    @test_tracker_info(uuid='a718e238-7e31-40c9-a45b-72081210cc73')
    @BluetoothBaseTest.bt_test_wrap
    def test_incoming_dial_re_hangup_re(self):
        """
        Tests if we can make a phone call from remote and disconnect from
        remote.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Make a call from RE role.
        2. Wait for the HF, AG to show ringing and RE to see the call dialing.
        3. Hangup the call on RE role.
        4. Wait for all devices to hangup the call.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        return self.dial_a_hangup_b(self.re, self.re, self.ag_phone_number)

    def test_bluetooth_voice_recognition_assistant(self):
        """
        Tests if we can initate a remote Voice Recognition session.

        Precondition:
        1. Devices are connected.

        Steps:
        1. Verify that audio isn't routed between the HF and AG.
        2. From the HF send a BVRA command.
        3. Verify that audio is routed from the HF to AG.
        4. From the HF send a BVRA command to stop the session.
        5. Verify that audio is no longer routed from the HF to AG.

        Returns:
          Pass if True
          Fail if False

        Priority: 0
        """
        audio_state = self.hf.droid.bluetoothHfpClientGetAudioState(
            self.ag.droid.bluetoothGetLocalAddress())
        if (audio_state != AUDIO_STATE_DISCONNECTED):
            self.log.info(
                "Audio connected before test started, current state {}.".
                format(str(audio_state)))
            return False
        bvra_started = self.hf.droid.bluetoothHfpClientStartVoiceRecognition(
            self.ag.droid.bluetoothGetLocalAddress())
        if (bvra_started != True):
            self.log.info("BVRA Failed to start.")
            return False
        time.sleep(SHORT_TIMEOUT)
        audio_state = self.hf.droid.bluetoothHfpClientGetAudioState(
            self.ag.droid.bluetoothGetLocalAddress())
        if (audio_state != AUDIO_STATE_ROUTED):
            self.log.info("Audio didn't route, current state {}.".format(
                str(audio_state)))
            return False
        bvra_stopped = self.hf.droid.bluetoothHfpClientStopVoiceRecognition(
            self.ag.droid.bluetoothGetLocalAddress())
        if (bvra_stopped != True):
            self.log.info("BVRA Failed to stop.")
            return False
        time.sleep(SHORT_TIMEOUT)
        audio_state = self.hf.droid.bluetoothHfpClientGetAudioState(
            self.ag.droid.bluetoothGetLocalAddress())
        if (audio_state != AUDIO_STATE_DISCONNECTED):
            self.log.info("Audio didn't cleanup, current state {}.".format(
                str(audio_state)))
            return False
        return True

    def dial_a_hangup_b(self, caller, callee, ph=""):
        """
        a, b and c can be either of AG, HF or Remote.
        1. Make a call from 'a' on a fixed number.
        2. Wait for the call to get connected (check on both 'a' and 'b')
           Check that 'c' is in ringing state.
        3. Hangup the call on 'b'.
        4. Wait for call to get completely disconnected
        (check on both 'a' and 'b')
        It is assumed that scenarios will not go into voice mail.
        """
        if ph == "": ph = self.re_phone_number

        # Determine if this is outgoing or incoming call.
        call_type = None
        if caller == self.ag or caller == self.hf:
            call_type = CALL_TYPE_OUTGOING
            if callee != self.ag and callee != self.hf:
                self.log.info("outgoing call should terminate at AG or HF")
                return False
        elif caller == self.re:
            call_type = CALL_TYPE_INCOMING
            if callee != self.re:
                self.log.info("Incoming call should terminate at Re")
                return False

        self.log.info("Call type is {}".format(call_type))

        # make a call on 'caller'
        if not tel_telecom_utils.dial_number(self.log, caller, ph):
            return False

        # Give time for state to update due to carrier limitations
        time.sleep(SHORT_TIMEOUT)
        # Check that everyone is in dialing/ringing state.
        ret = True
        if call_type == CALL_TYPE_OUTGOING:
            ret &= tel_telecom_utils.wait_for_dialing(self.log, self.hf)
            ret &= tel_telecom_utils.wait_for_dialing(self.log, self.ag)
            ret &= tel_telecom_utils.wait_for_ringing(self.log, self.re)
        else:
            ret &= tel_telecom_utils.wait_for_ringing(self.log, self.hf)
            ret &= tel_telecom_utils.wait_for_ringing(self.log, self.ag)
            ret &= tel_telecom_utils.wait_for_dialing(self.log, self.re)
        if not ret:
            return False

        # Give time for state to update due to carrier limitations
        time.sleep(SHORT_TIMEOUT)
        # Check if we have any calls with dialing or active state on 'b'.
        # We assume we never disconnect from 'ringing' state since it will lead
        # to voicemail.
        call_state_dialing_or_active = \
            [tel_defines.CALL_STATE_CONNECTING,
             tel_defines.CALL_STATE_DIALING,
             tel_defines.CALL_STATE_ACTIVE]

        calls_in_dialing_or_active = tel_telecom_utils.get_calls_in_states(
            self.log, callee, call_state_dialing_or_active)

        # Make sure there is only one!
        if len(calls_in_dialing_or_active) != 1:
            self.log.info("Call State in dialing or active failed {}".format(
                calls_in_dialing_or_active))
            return False

        # Hangup the *only* call on 'callee'
        if not car_telecom_utils.hangup_call(self.log, callee,
                                             calls_in_dialing_or_active[0]):
            return False

        time.sleep(SHORT_TIMEOUT)
        # Make sure everyone got out of in call state.
        for d in self.android_devices:
            ret &= tel_telecom_utils.wait_for_not_in_call(self.log, d)
        return ret
