#!/usr/bin/env python3

# Copyright 2020-present Open Networking Foundation
#
# SPDX-License-Identifier: LicenseRef-ONF-Member-Only-1.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()
