#/usr/bin/env python3.4
#
# 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.
"""
This test script exercises power test scenarios for GATT writing.
This test script was designed with this setup in mind:
Shield box one: Two Android Devices and Monsoon tool box
"""

import json
import os

from acts.test_utils.bt.BleEnum import ScanSettingsScanMode
from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
from acts.test_utils.bt.PowerBaseTest import PowerBaseTest
from acts.test_utils.bt.bt_test_utils import bluetooth_enabled_check
from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
from acts.utils import get_current_human_time
from acts.utils import sync_device_time


class GattPowerTest(PowerBaseTest):
    """Class for Gatt Power Test"""
    # Time to start GATT write
    START_TIME = 30
    # Repetitions
    REPETITIONS_40 = 40
    REPETITIONS_1 = 1
    # Time for GATT writing
    WRITE_TIME_60 = 60
    WRITE_TIME_3600 = 3600
    # Time for idle
    IDLE_TIME_30 = 30
    IDLE_TIME_0 = 0
    # Base commands for PMC
    PMC_GATT_CMD = ("am broadcast -a com.android.pmc.GATT ")
    GATT_SERVER_MSG = "%s--es GattServer 1" % (PMC_GATT_CMD)

    def __init__(self, controllers):
        PowerBaseTest.__init__(self, controllers)

        self.cen_ad = self.android_devices[0]
        self.per_ad = self.android_devices[1]

    def setup_class(self):
        super(GattPowerTest, self).setup_class()
        if not bluetooth_enabled_check(self.per_ad):
            self.log.error("Failed to turn on Bluetooth on peripheral")

        # Start PMC app for peripheral here
        # since base class has started PMC for central device
        self.per_ad.adb.shell(PowerBaseTest.START_PMC_CMD)
        self.per_ad.adb.shell(self.PMC_VERBOSE_CMD)

    def _measure_power_for_gatt_n_log_data(self, write_time, idle_time,
                                           repetitions):
        """Utility function for power test with GATT write.

        Steps:
        1. Prepare adb shell command for GATT server
        2. Send the adb shell command to PMC to startup GATT Server
        3. Prepare adb shell command for GATT Client
        4. Send the adb shell command to PMC to startup GATT Client
        5. PMC will start first alarm on GATT Client to start
           GATT write continuousely for "write_time" seconds
        6. After finishing writing for write_time it will stop for
           for "idle_time" seconds
        7  Repeat the write/idle cycle for "repetitions" times
        8. Save the power usage data into log file

        Args:
            write_time: time(sec) duration for writing GATT characteristic
            idle_time: time(sec) of idle (not write)
            repetitions: number of repetitions of writing cycles

        Returns:
            None
        """
        # Send message to Gatt Server
        self.per_ad.log.info("Send broadcast message to GATT Server: %s",
                             self.GATT_SERVER_MSG)
        self.per_ad.adb.shell(self.GATT_SERVER_MSG)

        # Send message to Gatt Client
        first_part_msg = "%s--es StartTime %d --es WriteTime %d" % (
            self.PMC_GATT_CMD, self.START_TIME, write_time)
        clientmsg = "%s --es IdleTime %d --es Repetitions %d" % (
            first_part_msg, idle_time, repetitions)
        self.cen_ad.log.info("Send broadcast message to GATT Client: %s",
                             clientmsg)
        self.cen_ad.adb.shell(clientmsg)

        sample_time = (write_time + idle_time) * repetitions
        # Start the power measurement
        result = self.mon.measure_power(self.POWER_SAMPLING_RATE, sample_time,
                                        self.current_test_name,
                                        self.START_TIME)
        # Calculate average and save power data into a file
        self.save_logs_for_power_test(result, write_time, idle_time)
        # Take bug report for peripheral device
        current_time = get_current_human_time()
        self.per_ad.take_bug_report(self.current_test_name, current_time)

    @BluetoothBaseTest.bt_test_wrap
    def test_power_for_60_sec_n_30_sec_idle_gatt_write(self):
        """Test power usage when do 60 sec GATT write & 30 sec idle

        Tests power usage when the test device do 60 sec GATT write
        and 30 sec idle with max MTU bytes after being connected.
        After each write GATT server will send a response
        back to GATT client so GATT client can do another write.

        Steps:
        1. Prepare adb shell command for GATT server
        2. Send the adb shell command to PMC to startup GATT Server
        3. Prepare adb shell command for GATT Client
        4. Send the adb shell command to PMC to startup GATT Client
        5. PMC will start first alarm on GATT Client
        6. Start power measurement
        7. Alarm will be triggered to start GATT write for 60 second
        8. Then it will be idle for 30 seconds
        9. Reconnect after idle time
        10. Repeat the cycles for 60 minutes
        11. End power measurement
        12. Save the power usage data into log file

        Expected Result:
        power consumption results

        TAGS: LE, GATT, Power
        Priority: 3
        """
        self._measure_power_for_gatt_n_log_data(
            self.WRITE_TIME_60, self.IDLE_TIME_30, self.REPETITIONS_40)

    @BluetoothBaseTest.bt_test_wrap
    def test_power_for_60_min_non_stop_gatt_write(self):
        """Test power usage when do a single GATT write.

        Tests power usage when the test device do 60 minutes of GATT write with
        max MTU bytes after being connected. After each write GATT server will
        send a response back to GATT client so GATT client can do another write.

        Steps:
        1. Prepare adb shell command for GATT server
        2. Send the adb shell command to PMC to startup GATT Server
        3. Prepare adb shell command for GATT Client
        4. Send the adb shell command to PMC to startup GATT Client
        5. PMC will start first alarm on GATT Client to start GATT write
        6. Start power measurement
        7. GATT server gets the write request after GATT Client sends a write
        8. GATT server sends a response back to GATT Client
        9. After GATT Client receive the response from GATT Server
           it will check if time reaches 60 minutes.
           if not it will write another characteristic
           otherwise it will stop writing
        10. Stop power measurement
        11. Save the power usage data into log file

        Expected Result:
        power consumption results

        TAGS: LE, GATT, Power
        Priority: 3
        """
        self._measure_power_for_gatt_n_log_data(
            self.WRITE_TIME_3600, self.IDLE_TIME_0, self.REPETITIONS_1)