#!/usr/bin/python3
"""
collectd exec plugin script for the Pace 5268AC modem as deployed by AT&T U-Verse
"""
from urllib.parse import urljoin
from urllib.request import urlopen
import time

import lxml.html

modem_url = 'http://192.168.0.1'
hostname = 'uverse'  # hostname to use when naming the collectd metrics.
instance = 'uverse'  # Instance name of the exec plugin.
interval = 30  # How many seconds between each collection?

broadband_status_url = urljoin(modem_url, '/xslt?PAGE=C_1_0')

while True:
    with urlopen(broadband_status_url, timeout=interval * 0.5) as response:
        doc = lxml.html.parse(response)
    timestamp = time.time()

    def putval(type, type_instance, fmt, *values):
        print('PUTVAL "{hostname}/exec-{instance}/{type}-{type_instance}" interval={interval} {timestamp:d}:{values}'.format(
            hostname=hostname,
            instance=instance,
            type=type,
            type_instance=type_instance,
            interval=interval,
            timestamp=int(timestamp),
            values=fmt.format(*values),
        ))

    for table in doc.findall('//table[@class="colortable"]'):
        caption = table.find('caption').text_content()

        if caption == "IP Traffic":
            for row in table.findall('tr'):
                title, *rest = [td.text_content() for td in row.findall('td')]
                if title == 'Transmit':
                    tx_bytes, tx_packets, tx_errors, tx_percent = rest
                elif title == 'Receive':
                    rx_bytes, rx_packets, rx_errors, rx_percent = rest

            putval('if_octets', 'ip_traffic', '{}:{}', rx_bytes, tx_bytes)
            putval('if_packets', 'ip_traffic', '{}:{}', rx_packets, tx_packets)
            putval('if_errors', 'ip_traffic', '{}:{}', rx_errors, tx_errors)

        elif caption == 'DSL : Aggregated Information':
            for row in table.findall('tr'):
                title, value, *rest = [td.text_content() for td in row.findall('td')]
                if title == 'Loss of Framing Failures':
                    putval('derive', 'framing_failures', '{}', value)
                elif title == 'Corrected Blocks':
                    putval('derive', 'corrected_blocks', '{}', value)
                elif title == 'Uncorrectable Blocks':
                    putval('derive', 'uncorrectable_blocks', '{}', value)

    time.sleep(interval - (time.time() - timestamp))
