#!/usr/bin/env python

# Copyright 2020-present Open Networking Foundation
#
# 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 os
import json
import logging
import enum
import requests
import time
import serial
from collections import namedtuple

'''
Simple script that checks Aether network operational status periodically
by controlling the attached 4G/LTE modem with AT commands and
report the result to the central monitoring server.
'''


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.INFO
)

report = {
    'name': CONF.edge_name,
    'status': {
        'control_plane': None,
        'user_plane': None
    }
}


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

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


class Modem():
    log = logging.getLogger('aether_edge_monitoring.Modem')

    read_timeout = 0.1

    def __init__(self, port, baudrate):
        self.port = port
        self.baudrate = baudrate
        self._response = None

    def connect(self):
        self.serial = serial.Serial(
            port=self.port,
            baudrate=self.baudrate,
            timeout=1)

    def _write(self, command):
        if self.serial.inWaiting() > 0:
            self.serial.flushInput()

        self._response = b""

        self.serial.write(bytearray(command + "\r", "ascii"))
        read = self.serial.inWaiting()
        while True:
            if read > 0:
                self._response += self.serial.read(read)
            else:
                time.sleep(self.read_timeout)
            read = self.serial.inWaiting()
            if read == 0:
                break
        return self._response.decode("ascii").replace('\r\n', ' ')

    def write(self, command, wait_resp=True):
        response = self._write(command)
        self.log.debug("%s: %s", command, response)

        if wait_resp and "ERROR" in response:
            return False, None
        return True, response

    def is_connected(self):
        success, result = self.write('AT+CGATT?')
        if not success or 'CGATT:' not in result:
            return State.error
        state = result.split('CGATT:')[1].split(' ')[0]
        return State(state)

    def close(self):
        self.serial.close()


def get_control_plane_state(modem):
    # Delete the existing session
    # "echo" works more stable than serial for this action
    # success, result = modem.write('AT+CFUN=0')
    logging.debug("echo 'AT+CFUN=0' > " + CONF.modem.port)
    success = os.system("echo 'AT+CFUN=0' > " + CONF.modem.port)
    logging.debug("result: %s", success)
    if success is not 0:
        msg = "Write 'AT+CFUN=0' failed"
        logging.error(msg)
        return State.error, msg

    # Wait until the modem is fully disconnected
    retry = 0
    state = None
    while retry < 5:
        state = modem.is_connected()
        if state is State.disconnected:
            break
        time.sleep(1)
        retry += 1

    # Consider the modem is not responding if disconnection failed
    if state is not State.disconnected:
        msg = "Failed to disconnect."
        logging.error(msg)
        return State.error, msg

    time.sleep(2)
    # Create a new session
    # "echo" works more stable than serial for this action
    # success, result = modem.write('AT+CGATT=1')
    logging.debug("echo 'AT+CFUN=1' > " + CONF.modem.port)
    success = os.system("echo 'AT+CFUN=1' > " + CONF.modem.port)
    logging.debug("result: %s", success)
    if success is not 0:
        msg = "Write 'AT+CFUN=1' failed"
        logging.error(msg)
        return State.error, msg

    # Give 10 sec for the modem to be fully connected
    retry = 0
    while retry < 10:
        state = modem.is_connected()
        if state is State.connected:
            break
        time.sleep(1)
        retry += 1
    # CGATT sometimes returns None
    if state is State.error:
        state = State.disconnected

    time.sleep(2)
    return state, None


def get_user_plane_state(modem):
    resp = os.system("ping -c 3 " + CONF.ping_to + ">/dev/null 2>&1")
    return State.connected if resp is 0 else State.disconnected, None


def report_status(cp_state, up_state):
    report['status']['control_plane'] = cp_state.name
    report['status']['user_plane'] = up_state.name

    logging.info("Sending report %s", report)
    try:
        result = requests.post(CONF.report_url, json=report)
    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():
    modem = Modem(CONF.modem.port, CONF.modem.baud)
    try:
        modem.connect()
    except serial.serialutil.SerialException as e:
        logging.error("Failed to connect the modem for %s", e)
        sys.exit(1)

    success = os.system("sudo ip route replace {}/32 via {}".format(
        CONF.ping_to, CONF.modem.ip_addr))
    if success is not 0:
        logging.error("Failed to add test routing.")
        sys.exit(1)

    while True:
        cp_state, cp_msg = get_control_plane_state(modem)
        up_state, up_msg = get_user_plane_state(modem)

        if cp_state is State.error:
            logging.error("Modem is in error state.")
            os.system("sudo shutdown -r now")

        report_status(cp_state, up_state)
        time.sleep(CONF.report_interval)

    modem.close()


if __name__ == "__main__":
    main()
