import re
import subprocess

from selenium.common.exceptions import WebDriverException

from lib_python import steps, execution, logger, variables
from lib_python.mobile.appium_server import start_appium_server, get_appium_driver
from lib_python.network import mount_network_drive
from libcrashtest.data.AndroidData import get_package_name, get_android_images_path, get_main_activity, get_wait_activity, get_apk_file_name
from libcrashtest.data.TestData import build_path, get_platform_type, is_local_test
import shutil
import os

_timeout = 1800  # seconds
__KEYCODE_BACK = 4


def deploy_android_emulator():
    """
    Deploys Android Emulator based on android image path from AndroidData.android_images and API version from TestData.get_platform_type()
    """
    import lib_python.mobile.android.emulator as emulator

    logger.info("Deploying Android emulator with API: {0}".format(get_platform_type()))

    android_images_path = os.path.join(get_android_images_path(), get_platform_type())
    emulator.deploy_android_emulator(get_platform_type(), android_images_path, timeout=_timeout)

    execution.passed()

steps.new_step("Deploy Android emulator", deploy_android_emulator)


def run_appium_server():
    """
    Runs Appium Server, which connects automatically to connected devices
    BEWARE on GRID machine with Genymotion you have to always deploy emulator at first
    """
    logger.info("Starting Appium server")

    start_appium_server(timeout=120)

    execution.passed()

steps.new_step("Run Appium server", run_appium_server)


# def install_apk_on_android_emulator():
#     """
#     Installs Android apk on running Emulator, in case that this build is already present it will only reconnect Appium Driver
#     """
#
#     # In case of local test skip build preparation part
#     if is_local_test():
#         logger.info("Local test detected!")
#         logger.info("Application to be installed from path: {0}".format(build_path))
#         local_app = build_path
#     else:
#         # TODO: cleanup
#         pass
#     #     # Path to app on local station ready for installation via Appium
#     #     local_app = os.path.join(os.environ["USERPROFILE"], "presenter_apk", os.path.basename(os.path.normpath(build_path)), get_apk_file_name())
#     #
#     #     # Mounting network drive to access apk file on sonus build server
#     #     network.mount_network_drive("s:", build_path, "cz\\tester", "test")
#     #
#     #     # If local app is already present, only relaunch application and create new driver
#     #     if os.path.exists(local_app):
#     #         logger.info("Presenter build: {0} - Is already installed on Android Emulator".format(os.path.basename(os.path.normpath(build_path))))
#     #         logger.info("Connecting Appium driver to application already installed in Emulator with API: {0}".format(get_platform_type().rpartition("-")[2]))
#     #         local_app = ""
#     #
#     #     # In case of clean installation, copy apk file to desired path
#     #     else:
#     #         if not os.path.exists(os.path.dirname(local_app)):
#     #             os.makedirs(os.path.dirname(local_app))
#     #         shutil.copy(os.path.join(r"s:\presenter", get_apk_file_name()), local_app)
#     #         logger.info("Application copied to local destination: \n {0}".format(local_app))
#     #         logger.info("Installation of build: {0} - HAS BEGUN!".format(os.path.basename(os.path.normpath(build_path))))
#     #
#     # # Installation itself and store Appium Webdriver into variables.driver
#     # variables.driver = appium_server.get_appium_driver(get_package_name(), get_main_activity(), get_wait_activity(), local_app)
#     variables.driver = appium_server.get_appium_driver('com.avg.zaap.crash',
#                                                        'com.avg.zaap.crash.MainActivity',
#                                                        'com.avg.zaap.crash.MainActivity',
#                                                        local_app)
#
#     # # In case of simulator is present, redirect ports for communication
#     # if is_platform_simulator_present() and not is_local_test() and not is_genymotion():
#     #     import lib_python.mobile.android.adutils as adutils
#     #     logger.info("Platform Simulator is present -> Port redirection")
#     #     adutils.AndroidUtils().redirect_port(6969, 6969)
#
#     execution.passed()
#
# steps.new_step("Install Presenter build on Android emulator", install_apk_on_android_emulator)

def install_apk_on_android_emulator():
    """
    Installs Android apk on running Emulator, in case that this build is already present it will only reconnect Appium Driver
    """

    # In case of local test skip build preparation part
    if is_local_test():
        logger.info("Local test detected!")
        logger.info("Application to be installed from path: {0}".format(build_path))
        local_app = build_path
    else:
        # Path to app on local station ready for installation via Appium
        local_app = os.path.join(os.environ["USERPROFILE"], "crash_apk", os.path.basename(os.path.normpath(build_path)), get_apk_file_name())
        cap_server_path = os.path.join(os.environ["USERPROFILE"], "capserver")

        # Mounting network drive to access apk file on sonus build server
        mount_network_drive("s:", build_path.rstrip("\\"), "cz\\tester", "test", force=True)

        # If local app is already present, only relaunch application and create new driver
        if os.path.exists(local_app):
            logger.info("Presenter build: {0} - Is already installed on Android Emulator".format(os.path.basename(os.path.normpath(build_path))))
            logger.info("Connecting Appium driver to application already installed in Emulator with API: {0}".format(get_platform_type().rpartition("-")[2]))
            local_app = ""

        # In case of clean installation, copy apk file to desired path
        else:
            if not os.path.exists(os.path.dirname(local_app)):
                os.makedirs(os.path.dirname(local_app))

            # copy apk
            shutil.copy(os.path.join(r"s:\apk", get_apk_file_name()), local_app)

            # copy CAP mock server and its dependencies
            shutil.copytree(r"s:\jar", cap_server_path)

            logger.info("Application copied to local destination: \n {0}".format(local_app))
            logger.info("Installation of build: {0} - HAS BEGUN!".format(os.path.basename(os.path.normpath(build_path))))

    attempt = 0
    _max_attempts = 3
    _pattern = re.compile("mFocusedActivity: ActivityRecord{[\s\S]*com\.android\.launcher[\s\S]*}")

    while attempt < _max_attempts:
        attempt += 1

        try:
            # Installation itself and store Appium Webdriver into variables.driver
            variables.driver = get_appium_driver(get_package_name(), get_main_activity(), get_wait_activity(), local_app)
            execution.passed()
            return

        except WebDriverException, e:
            logger.warning("WebDriverException called, trying to handle the cause")

            if e.message.find("unlock") != -1:  # exception message contains unlock
                # assume it's "Screen did not unlock"
                launcher_displayed = False

                while not launcher_displayed:
                    # punch in the BACK key
                    variables.driver.press_keycode(__KEYCODE_BACK)

                    current_activity = subprocess.check_output("adb shell dumpsys activity activities", shell=True)
                    launcher_displayed = _pattern.match(current_activity) is not None

                    logger.debug(current_activity)
                    logger.error(_pattern.match(current_activity))

            else:
                error_message = "WebDriverException: {0}".format(str(e))
                logger.error(error_message)
                execution.error(error_message)

    execution.passed()

steps.new_step("Install Presenter build on Android emulator", install_apk_on_android_emulator)
