#!/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 script to test PBAP contact download between two devices which can run SL4A.
"""

import os
import time

from acts.test_decorators import test_tracker_info
from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
from acts.test_utils.bt.bt_test_utils import setup_multiple_devices_for_bt_test
from acts.base_test import BaseTestClass
from acts.test_utils.bt import bt_contacts_utils
from acts.test_utils.bt import bt_test_utils
from acts.test_utils.car import car_bt_utils
from acts.utils import exe_cmd
import acts.test_utils.bt.BtEnum as BtEnum

# Offset call logs by 1 minute
CALL_LOG_TIME_OFFSET_IN_MSEC = 60000
PSE_CONTACTS_FILE = "psecontacts.vcf"
PCE_CONTACTS_FILE = "pcecontacts.vcf"
MERGED_CONTACTS_FILE = "psecombined.vcf"
STANDART_CONTACT_COUNT = 100


class BtCarPbapTest(BluetoothBaseTest):
    contacts_destination_path = ""

    def __init__(self, controllers):
        BaseTestClass.__init__(self, controllers)
        self.pce = self.android_devices[0]
        self.pse = self.android_devices[1]
        self.pse2 = self.android_devices[2]
        self.contacts_destination_path = self.log_path + "/"

    def setup_class(self):
        if not super(BtCarPbapTest, self).setup_class():
            return False
        permissions_list = [
            "android.permission.READ_CONTACTS",
            "android.permission.WRITE_CONTACTS",
            "android.permission.READ_EXTERNAL_STORAGE"
        ]
        for device in self.android_devices:
            for permission in permissions_list:
                device.adb.shell(
                    "pm grant com.google.android.contacts {}".format(permission))

        # Pair the devices.
        # This call may block until some specified timeout in bt_test_utils.py.
        # Grace time inbetween stack state changes
        if not bt_test_utils.pair_pri_to_sec(self.pce, self.pse):
            self.log.error("Failed to pair.")
            return False
        time.sleep(3)
        if not bt_test_utils.pair_pri_to_sec(self.pce, self.pse2):
            self.log.error("Failed to pair.")
            return False

        # Disable the HFP and A2DP profiles. This will ensure only PBAP
        # gets connected. Also, this will eliminate the auto-connect loop.
        car_bt_utils.set_car_profile_priorities_off(self.pce, self.pse)
        car_bt_utils.set_car_profile_priorities_off(self.pce, self.pse2)

        # Enable PBAP on PSE & PCE.

        self.pse.droid.bluetoothChangeProfileAccessPermission(
            self.pce.droid.bluetoothGetLocalAddress(),
            BtEnum.BluetoothProfile.PBAP_SERVER.value,
            BtEnum.BluetoothAccessLevel.ACCESS_ALLOWED.value)

        self.pse2.droid.bluetoothChangeProfileAccessPermission(
            self.pce.droid.bluetoothGetLocalAddress(),
            BtEnum.BluetoothProfile.PBAP_SERVER.value,
            BtEnum.BluetoothAccessLevel.ACCESS_ALLOWED.value)

        bt_test_utils.set_profile_priority(
            self.pce, self.pse, [BtEnum.BluetoothProfile.PBAP_CLIENT],
            BtEnum.BluetoothPriorityLevel.PRIORITY_ON)
        bt_test_utils.set_profile_priority(
            self.pce, self.pse2, [BtEnum.BluetoothProfile.PBAP_CLIENT],
            BtEnum.BluetoothPriorityLevel.PRIORITY_ON)

        return True

    def setup_test(self):
        if not super(BtCarPbapTest, self).setup_test():
            return False
        self.pse.droid.callLogsEraseAll()
        return self.erase_all_contacts()

    def teardown_test(self):
        if not super(BtCarPbapTest, self).teardown_test():
            return False
        for device in self.android_devices:
            bt_contacts_utils.delete_vcf_files(device)

        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse.droid.bluetoothGetLocalAddress())
        return self.erase_all_contacts()

    def erase_all_contacts(self):
        try:
            return all(bt_contacts_utils.erase_contacts(device) for device in self.android_devices)
        finally:
            # Allow all content providers to synchronize.
            time.sleep(1)

    def verify_contacts_match(self):
        bt_contacts_utils.export_device_contacts_to_vcf(
            self.pce, self.contacts_destination_path, PCE_CONTACTS_FILE)
        return bt_contacts_utils.count_contacts_with_differences(
            self.contacts_destination_path, PCE_CONTACTS_FILE,
            PSE_CONTACTS_FILE) == 0

    def connect_and_verify(self, count):
        bt_test_utils.connect_pri_to_sec(
            self.pce, self.pse,
            set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
        bt_contacts_utils.wait_for_phone_number_update_complete(self.pce,
                                                                count)
        contacts_added = self.verify_contacts_match()
        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse.droid.bluetoothGetLocalAddress())
        contacts_removed = bt_contacts_utils.wait_for_phone_number_update_complete(
            self.pce, 0)
        return contacts_added and contacts_removed

    @test_tracker_info(uuid='7dcdecfc-42d1-4f41-b66e-823c8f161356')
    @BluetoothBaseTest.bt_test_wrap
    def test_pbap_connect_and_disconnect(self):
        """Test Connectivity

        Test connecting with the server enabled and disabled

        Precondition:
        1. Devices are paired.

        Steps:
        1. Disable permission on PSE to prevent PCE from connecting
        2. Attempt to connect PCE to PSE
        3. Verify connection failed
        4. Enable permission on PSE to allow PCE to connect
        5. Attempt to connect PCE to PSE
        6. Verify connection succeeded

        Returns:
            Pass if True
            Fail if False
        """
        self.pse.droid.bluetoothChangeProfileAccessPermission(
            self.pce.droid.bluetoothGetLocalAddress(),
            BtEnum.BluetoothProfile.PBAP_SERVER.value,
            BtEnum.BluetoothAccessLevel.ACCESS_DENIED.value)
        if bt_test_utils.connect_pri_to_sec(
                self.pce, self.pse,
                set([BtEnum.BluetoothProfile.PBAP_CLIENT.value])):
            self.log.error("Client connected and shouldn't be.")
            return False

        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse.droid.bluetoothGetLocalAddress())

        self.pse.droid.bluetoothChangeProfileAccessPermission(
            self.pce.droid.bluetoothGetLocalAddress(),
            BtEnum.BluetoothProfile.PBAP_SERVER.value,
            BtEnum.BluetoothAccessLevel.ACCESS_ALLOWED.value)

        if not bt_test_utils.connect_pri_to_sec(
                self.pce, self.pse,
                set([BtEnum.BluetoothProfile.PBAP_CLIENT.value])):
            self.log.error("No client connected and should be.")
            return False

        return True

    @test_tracker_info(uuid='1733efb9-71af-4956-bd3a-0d3167d94d0c')
    @BluetoothBaseTest.bt_test_wrap
    def test_contact_download(self):
        """Test Contact Download

        Test download of contacts from a clean state.

        Precondition:
        1. Devices are paired.

        Steps:
        1. Erase contacts from PSE and PCE.
        2. Add a predefined list of contacts to PSE.
        3. Connect PCE to PSE to perform transfer.
        4. Compare transfered contacts.
        5. Disconnect.
        6. Verify PCE cleaned up contact list.

        Returns:
            Pass if True
            Fail if False
        """
        bt_contacts_utils.generate_contact_list(self.contacts_destination_path,
                                                PSE_CONTACTS_FILE, 100)
        phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
            self.pse, self.contacts_destination_path, PSE_CONTACTS_FILE)
        bt_test_utils.connect_pri_to_sec(
            self.pce, self.pse,
            set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
        bt_contacts_utils.wait_for_phone_number_update_complete(
            self.pce, phone_numbers_added)
        if not self.verify_contacts_match():
            return False
        return bt_contacts_utils.erase_contacts(self.pce)

    @test_tracker_info(uuid='99dc6ac6-b7cf-45ce-927b-8c4ebf8ab664')
    @BluetoothBaseTest.bt_test_wrap
    def test_modify_phonebook(self):
        """Test Modify Phonebook

        Test changing contacts and reconnecting PBAP.

        Precondition:
        1. Devices are paired.

        Steps:
        1. Add a predefined list of contacts to PSE.
        2. Connect PCE to PSE to perform transfer.
        3. Verify that contacts match.
        4. Change some contacts on the PSE.
        5. Reconnect PCE to PSE to perform transfer.
        6. Verify that new contacts match.

        Returns:
            Pass if True
            Fail if False
        """
        bt_contacts_utils.generate_contact_list(self.contacts_destination_path,
                                                PSE_CONTACTS_FILE, 100)
        phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
            self.pse, self.contacts_destination_path, PSE_CONTACTS_FILE)
        if not self.connect_and_verify(phone_numbers_added):
            return False

        bt_contacts_utils.erase_contacts(self.pse)
        bt_contacts_utils.generate_contact_list(self.contacts_destination_path,
                                                PSE_CONTACTS_FILE, 110, 2)
        phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
            self.pse, self.contacts_destination_path, PSE_CONTACTS_FILE)
        return self.connect_and_verify(phone_numbers_added)

    @test_tracker_info(uuid='bbe31bf5-51e8-4175-b266-1c7750e44f5b')
    @BluetoothBaseTest.bt_test_wrap
    def test_special_contacts(self):
        """Test Special Contacts

        Test numerous special cases of contacts that could cause errors.

        Precondition:
        1. Devices are paired.

        Steps:
        1. Add a predefined list of contacts to PSE that includes special cases:
        2. Connect PCE to PSE to perform transfer.
        3. Verify that contacts match.

        Returns:
            Pass if True
            Fail if False
        """

        vcards = []

        # Generate a contact with no email address
        current_contact = bt_contacts_utils.VCard()
        current_contact.first_name = "Mr."
        current_contact.last_name = "Smiley"
        current_contact.add_phone_number(
            bt_contacts_utils.generate_random_phone_number())
        vcards.append(current_contact)

        # Generate a 2nd contact with the same name but different phone number
        current_contact = bt_contacts_utils.VCard()
        current_contact.first_name = "Mr."
        current_contact.last_name = "Smiley"
        current_contact.add_phone_number(
            bt_contacts_utils.generate_random_phone_number())
        vcards.append(current_contact)

        # Generate a contact with no name
        current_contact = bt_contacts_utils.VCard()
        current_contact.email = "{}@gmail.com".format(
            bt_contacts_utils.generate_random_string())
        current_contact.add_phone_number(
            bt_contacts_utils.generate_random_phone_number())
        vcards.append(current_contact)

        # Generate a contact with random characters in its name
        current_contact = bt_contacts_utils.VCard()
        current_contact.first_name = bt_contacts_utils.generate_random_string()
        current_contact.last_name = bt_contacts_utils.generate_random_string()
        current_contact.add_phone_number(
            bt_contacts_utils.generate_random_phone_number())
        vcards.append(current_contact)

        # Generate a contact with only a phone number
        current_contact = bt_contacts_utils.VCard()
        current_contact.add_phone_number(
            bt_contacts_utils.generate_random_phone_number())
        vcards.append(current_contact)

        # Generate a 2nd contact with only a phone number
        current_contact = bt_contacts_utils.VCard()
        current_contact.add_phone_number(
            bt_contacts_utils.generate_random_phone_number())
        vcards.append(current_contact)

        bt_contacts_utils.create_new_contacts_vcf_from_vcards(
            self.contacts_destination_path, PSE_CONTACTS_FILE, vcards)

        phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
            self.pse, self.contacts_destination_path, PSE_CONTACTS_FILE)
        return self.connect_and_verify(phone_numbers_added)

    @test_tracker_info(uuid='2aa2bd00-86cc-4f39-a06a-90b17ea5b320')
    @BluetoothBaseTest.bt_test_wrap
    def test_call_log(self):
        """Test Call Log

        Test that Call Logs are transfered

        Precondition:
        1. Devices are paired.

        Steps:
        1. Add a predefined list of calls to the PSE call log.
        2. Connect PCE to PSE to allow call log transfer
        3. Verify the Missed, Incoming, and Outgoing Call History

        Returns:
            Pass if True
            Fail if False
        """
        bt_contacts_utils.add_call_log(
            self.pse, bt_contacts_utils.INCOMMING_CALL_TYPE,
            bt_contacts_utils.generate_random_phone_number().phone_number,
            int(time.time() * 1000))
        bt_contacts_utils.add_call_log(
            self.pse, bt_contacts_utils.INCOMMING_CALL_TYPE,
            bt_contacts_utils.generate_random_phone_number().phone_number,
            int(time.time()) * 1000 - 4 * CALL_LOG_TIME_OFFSET_IN_MSEC)
        bt_contacts_utils.add_call_log(
            self.pse, bt_contacts_utils.OUTGOING_CALL_TYPE,
            bt_contacts_utils.generate_random_phone_number().phone_number,
            int(time.time()) * 1000 - CALL_LOG_TIME_OFFSET_IN_MSEC)
        bt_contacts_utils.add_call_log(
            self.pse, bt_contacts_utils.MISSED_CALL_TYPE,
            bt_contacts_utils.generate_random_phone_number().phone_number,
            int(time.time()) * 1000 - 2 * CALL_LOG_TIME_OFFSET_IN_MSEC)
        bt_contacts_utils.add_call_log(
            self.pse, bt_contacts_utils.MISSED_CALL_TYPE,
            bt_contacts_utils.generate_random_phone_number().phone_number,
            int(time.time()) * 1000 - 2 * CALL_LOG_TIME_OFFSET_IN_MSEC)

        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse.droid.bluetoothGetLocalAddress())
        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse2.droid.bluetoothGetLocalAddress())

        bt_test_utils.connect_pri_to_sec(
            self.pce, self.pse,
            set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
        pse_call_log_count = self.pse.droid.callLogGetCount()
        self.log.info("Waiting for {} call logs to be transfered".format(
            pse_call_log_count))
        bt_contacts_utils.wait_for_call_log_update_complete(self.pce,
                                                            pse_call_log_count)

        if not bt_contacts_utils.get_and_compare_call_logs(
                self.pse, self.pce, bt_contacts_utils.INCOMMING_CALL_TYPE):
            return False
        if not bt_contacts_utils.get_and_compare_call_logs(
                self.pse, self.pce, bt_contacts_utils.OUTGOING_CALL_TYPE):
            return False
        if not bt_contacts_utils.get_and_compare_call_logs(
                self.pse, self.pce, bt_contacts_utils.MISSED_CALL_TYPE):
            return False

        return True

    @test_tracker_info(uuid='bb018bf4-5a61-478d-acce-eef88050e489')
    @BluetoothBaseTest.bt_test_wrap
    def test_multiple_phones(self):
        """Test Multiple Phones

        Test that connects two phones and confirms contacts are transfered
        and merged while still being associated with their original phone.

        Precondition:
        1. Devices are paired.

        Steps:
        1. Add a unique list of contacts to PSE on each phone.
        2. Connect PCE to PSE 1 to perform transfer.
        3. Verify contacts match.
        4. Connect PCE to PSE 2 to perform transfer.
        5. Verify that the PCE has a union set of contacts from
           PSE 1 and PSE 2.
        6. Disconnect PCE from PSE 1 to clean up contacts.
        7. Verify that only PSE 2 contacts remain on PCE and they match.
        8. Disconnect PCE from PSE 2 to clean up contacts.

        Returns:
           Pass if True
           Fail if False
        """
        PSE1_CONTACTS_FILE = "{}{}".format(PSE_CONTACTS_FILE, "1")
        PSE2_CONTACTS_FILE = "{}{}".format(PSE_CONTACTS_FILE, "2")

        bt_contacts_utils.generate_contact_list(self.contacts_destination_path,
                                                PSE1_CONTACTS_FILE, 100)
        bt_contacts_utils.import_device_contacts_from_vcf(self.pse,
            self.contacts_destination_path,
            PSE1_CONTACTS_FILE)
        bt_contacts_utils.generate_contact_list(self.contacts_destination_path,
                                                PSE2_CONTACTS_FILE, 100)
        bt_contacts_utils.import_device_contacts_from_vcf(self.pse2,
            self.contacts_destination_path,
            PSE2_CONTACTS_FILE)

        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse.droid.bluetoothGetLocalAddress())
        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse2.droid.bluetoothGetLocalAddress())

        bt_test_utils.connect_pri_to_sec(
            self.pce, self.pse,
            set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
        bt_contacts_utils.wait_for_phone_number_update_complete(self.pce, 100)
        bt_contacts_utils.export_device_contacts_to_vcf(
            self.pce, self.contacts_destination_path, PCE_CONTACTS_FILE)
        pse1_matches = bt_contacts_utils.count_contacts_with_differences(
            self.contacts_destination_path, PCE_CONTACTS_FILE,
            PSE1_CONTACTS_FILE) == 0

        bt_test_utils.connect_pri_to_sec(
            self.pce, self.pse2,
            set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
        bt_contacts_utils.wait_for_phone_number_update_complete(self.pce, 200)
        bt_contacts_utils.export_device_contacts_to_vcf(
            self.pce, self.contacts_destination_path, PCE_CONTACTS_FILE)

        merged_file = open('{}{}'.format(self.contacts_destination_path,
                                         MERGED_CONTACTS_FILE), 'w')
        for contacts_file in [PSE1_CONTACTS_FILE, PSE2_CONTACTS_FILE]:
            infile = open(self.contacts_destination_path + contacts_file)
            merged_file.write(infile.read())

        self.log.info("Checking combined phonebook.")
        pse1andpse2_matches = bt_contacts_utils.count_contacts_with_differences(
            self.contacts_destination_path, PCE_CONTACTS_FILE,
            MERGED_CONTACTS_FILE) == 0

        self.pce.droid.bluetoothPbapClientDisconnect(
            self.pse.droid.bluetoothGetLocalAddress())
        bt_contacts_utils.wait_for_phone_number_update_complete(self.pce, 100)

        self.log.info("Checking phonebook after disconnecting first device.")
        bt_contacts_utils.export_device_contacts_to_vcf(
            self.pce, self.contacts_destination_path, PCE_CONTACTS_FILE)
        pse2_matches = bt_contacts_utils.count_contacts_with_differences(
            self.contacts_destination_path, PCE_CONTACTS_FILE,
            PSE2_CONTACTS_FILE) == 0

        bt_contacts_utils.erase_contacts(self.pse)
        bt_contacts_utils.erase_contacts(self.pse2)
        return pse1_matches and pse2_matches and pse1andpse2_matches

