#!/usr/bin/env python3
#
#   Copyright 2021 - 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.



import sys
import collections
import random
import time
import datetime
import os
import logging
import json
import subprocess
import math
import re

from acts import asserts
from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
from acts_contrib.test_utils.tel.GFTInOutBaseTest import GFTInOutBaseTest
from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH
from acts.controllers.android_device import DEFAULT_SDM_LOG_PATH
from acts_contrib.test_utils.tel.tel_test_utils import hangup_call
from acts_contrib.test_utils.tel.tel_test_utils import initiate_call
from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_volte

from acts.test_decorators import test_tracker_info
from acts.logger import epoch_to_log_line_timestamp
from acts.utils import get_current_epoch_time
from acts.libs.utils.multithread import multithread_func

from acts_contrib.test_utils.tel.gft_inout_defines import NO_SERVICE_POWER_LEVEL
from acts_contrib.test_utils.tel.gft_inout_defines import IN_SERVICE_POWER_LEVEL
from acts_contrib.test_utils.tel.gft_inout_defines import NO_SERVICE_AREA
from acts_contrib.test_utils.tel.gft_inout_defines import IN_SERVICE_AREA
from acts_contrib.test_utils.tel.gft_inout_defines import WIFI_AREA
from acts_contrib.test_utils.tel.gft_inout_defines import NO_WIFI_AREA
from acts_contrib.test_utils.tel.gft_inout_defines import NO_SERVICE_TIME
from acts_contrib.test_utils.tel.gft_inout_defines import WAIT_FOR_SERVICE_TIME


class TelLabGFTModemConnectivityHelperTest(GFTInOutBaseTest):
    def __init__(self, controllers):
        GFTInOutBaseTest.__init__(self, controllers)

    def setup_test(self):
        self.adjust_cellular_signal(IN_SERVICE_POWER_LEVEL)
        self.adjust_wifi_signal(IN_SERVICE_POWER_LEVEL)
        GFTInOutBaseTest.setup_test(self)
        self.check_network()


    """Tests"""
    @test_tracker_info(uuid="c602e556-8273-4c75-b8fa-4d51ba514654")
    @TelephonyBaseTest.tel_test_wrap
    def test_in_out_no_service(self):
        """In/Out service - Stationary idle mode - 1 min
            UE is in idle
            Move UE from coverage area to no service area and UE shows no service
            Wait for 1 min, then re-enter coverage area

            Returns:
                True if pass; False if fail.
        """
        self.adjust_cellular_signal(NO_SERVICE_POWER_LEVEL)
        self.adjust_wifi_signal(NO_SERVICE_POWER_LEVEL)
        time.sleep(NO_SERVICE_TIME)
        self.adjust_cellular_signal(IN_SERVICE_POWER_LEVEL)
        self.adjust_wifi_signal(IN_SERVICE_POWER_LEVEL)
        time.sleep(WAIT_FOR_SERVICE_TIME)
        if not self.check_network():
          return False
        return True


    @test_tracker_info(uuid="e58c7347-a930-4a3a-a740-a6d1cfb19ca0")
    @TelephonyBaseTest.tel_test_wrap
    def test_volte_call_cellular(self, loop=1):
        """ UE is in call
            Move UE from coverage area to no service area and UE shows no service
            Wait for 1 min, then re-enter coverage area

            Args:
                loop: cycle
            Returns:
                True if pass; False if fail.
        """
        test_result = True
        for x in range (loop):
            self.log.info("%s loop: %s/%s" %(self.current_test_name,x+1, loop))
            self.adjust_cellular_signal(IN_SERVICE_POWER_LEVEL)
            self.adjust_wifi_signal(IN_SERVICE_POWER_LEVEL)

            # Make a MO VoLTE call in service area.
            tasks = [(self._initiate_call, (ad, )) for ad in self.android_devices]
            if not multithread_func(self.log, tasks):
                return False
            tasks = [(is_phone_in_call_volte, (ad.log, ad, )) for ad in self.android_devices]
            test_result = multithread_func(self.log, tasks)

            # Move to poor service -> no service area
            self.adjust_atten_slowly(10, NO_SERVICE_AREA)
            time.sleep(NO_SERVICE_TIME)
            # check call status
            tasks = [(is_phone_in_call_volte, (ad.log, ad, )) for ad in self.android_devices]
            test_result = multithread_func(self.log, tasks)
            for ad in self.android_devices:
                telecom_state = ad.droid.telecomGetCallState()
                ad.log.info("telecom_state %s" %(telecom_state))
            # Move back to service area
            self.adjust_atten_slowly(10, IN_SERVICE_AREA)
            time.sleep(WAIT_FOR_SERVICE_TIME)
        return test_result

    def _initiate_call(self, ad):
        """ initiate a voice call

        Args:
            ad: caller

        Returns:
            return True if call initiate successfully
        """
        mt = ad.mt_phone_number
        ad.log.info("set mt number to %s" %(mt))
        ad.log.info("check network status before initiate call")
        self.check_network()
        ad.log.info("_initiate_call to %s" %(mt))
        if not initiate_call(self.log, ad, mt):
            return False
        return True
