#!/usr/bin/env python3

# Copyright 2020-present Open Networking Foundation
#
# SPDX-License-Identifier: Apache-2.0

import sys
import os
import time
import requests
import json
import enum
import logging
from collections import namedtuple
from pyadb import ADB

'''
Check Aether network operational status and report it to
central monitoring server

1) check mobile connctivity after toggling the airplane mode
2) check if ping to 8.8.8.8 works
'''

CONF = json.loads(
    open(os.getenv('CONFIG_FILE', "./config.json")).read(),
    object_hook=lambda d: namedtuple('X', d.keys())(*d.values())
)

logging.basicConfig(
    filename=CONF.log_file,
    format='%(asctime)s [%(levelname)s] %(message)s',
    level=logging.WARN
)

ADB_GET_COMMANDS = {
    "apn_mode": "settings get global airplane_mode_on",
    "lte_state": "dumpsys telephony.registry | grep -m1 mDataConnectionState",
    "ping_result": "ping -c 3 8.8.8.8&>/dev/null; echo $?",
    "ping_dns_result": "ping -c 10 " + "8.8.8.8" +
                    " | tail -1 | awk '{print $4}'"
}
ADB_APN_COMMANDS = {
    "home": "input keyevent 3",
    "setting": "am start -a android.settings.AIRPLANE_MODE_SETTINGS",
    "toggle": "input tap " + \
              CONF.adb.apn_mode_toggle_location.x + " " + \
              CONF.adb.apn_mode_toggle_location.y
}


class State(enum.Enum):
    error = "-1"
    disconnected = "0"
    connecting = "1"
    connected = "2"

    @classmethod
    def has_value(cls, value):
        return value in cls._value2member_map_


edge_status = {
    'name': CONF.edge_name,
    'status': {
        'control_plane': None,
        'user_plane': 'connected'
    },
    'speedtest': {
        'ping': {
            'dns': {
                'min': 0.0,
                'avg': 0.0,
                'max': 0.0,
                'stddev': 0.0
            }
        }
    }
}


def _run_adb_shell(adb, command):
    result, error = adb.shell_command(command)
    # error is returned even when succeeded
    # so ignore error value here
    if result:
        logging.debug(result)
    time.sleep(2)
    result = result[0] if result is not None else None
    return True, result


def get_control_plane_state(adb):
    '''
    check aether control plane works by toggling airplane mode
    '''
    # get the current airplane mode
    success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['apn_mode'])
    if not success or result is None:
        return State.error, result
    apn_mode_on = True if result == "1" else False

    # toggle the airplane mode
    for command in ADB_APN_COMMANDS.values():
        success, result = _run_adb_shell(adb, command)
        if not success:
            return State.error, result
    if not apn_mode_on:
        success, result = _run_adb_shell(adb, ADB_APN_COMMANDS['toggle'])
        if not success:
            return State.error, result

    # get connection state
    state = State.connecting.value
    retry_count = 10
    while retry_count > 0:
        success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['lte_state'])
        if not success or result is None:
            continue
        state = result.split("=")[1]
        if state == State.connected.value:
            break
        time.sleep(1)
        retry_count -= 1

    if not State.has_value(state):
        return State.error, None
    return State(state), None


def get_user_plane_state(adb):
    '''
    checks aether user plane connectivity with ping to 8.8.8.8
    '''
    success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['ping_result'])
    if not success or result is None:
        return State.error, result

    state = State.connected if result == "0" else State.disconnected
    return state, None


def run_ping_test(adb, ip, count):
    '''
    Runs the ping test
    Input: IP to ping, # times to ping
    Returns: dict of the min/avg/max/stddev numbers from the ping command result
    '''
    result = {'min': 0.0,
              'avg': 0.0,
              'max': 0.0,
              'stddev': 0.0}
    try:
        commandResult, commandOutput = _run_adb_shell(adb, ADB_GET_COMMANDS['ping_dns_result'])
        pingResult = commandOutput.split("/")
        result = {'min': float(pingResult[0]),
                  'avg': float(pingResult[1]),
                  'max': float(pingResult[2]),
                  'stddev': float(pingResult[3])}
    except Exception as e:
        logging.error("Ping test failed for " + ip + ": %s", e)
    return result


def get_ping_test(adb):
    '''
    Each ping test result saves the min/avg/max/stddev to dict.
    1) Performs ping test to Google Public DNS for 10 iterations.
    2) # TODO: Performs ping to device on network.
    '''
    speedtest_ping = {}
    speedtest_ping['dns'] = run_ping_test(adb, "8.8.8.8", 10)
    return speedtest_ping


def report_aether_network_state():
    '''
    report the aether network state to the monitoring server
    '''
    logging.info("Sending report %s", edge_status)
    try:
        result = requests.post(CONF.report_url, json=edge_status)
    except requests.exceptions.ConnectionError:
        logging.error("Failed to report for %s", e)
        pass
    try:
        result.raise_for_status()
    except requests.exceptions.HTTPError as e:
        logging.error("Failed to report for %s", e)
        pass


def main():
    adb = ADB()
    if adb.set_adb_path(CONF.adb.path) is False:
        logging.error(CONF.adb.path + " not found")
        sys.exit(1)

    dev = adb.get_devices()
    if len(dev) == 0:
      logging.error("No device found")
      sys.exit(1)

    adb.set_target_device(dev[0])
    success, result = _run_adb_shell(adb, "svc data enable")
    if not success:
        logging.error("Failed to turn data on")
        sys.exit(1)

    while True:
        _run_adb_shell(adb, "svc power stayon true")
        cp_state, err = get_control_plane_state(adb)
        up_state, err = get_user_plane_state(adb)
        speedtest_ping = get_ping_test(adb)

        edge_status['status']['control_plane'] = cp_state.name
        edge_status['status']['user_plane'] = up_state.name
        edge_status['speedtest']['ping'] = speedtest_ping

        report_aether_network_state()
        _run_adb_shell(adb, "svc power stayon false")

        time.sleep(CONF.report_interval)


if __name__ == "__main__":
    main()
