#!/usr/bin/env python
"""igcollect - Artfiles Uplink Traffic

Copyright (c) 2017 InnoGames GmbH
"""

import logging
from argparse import ArgumentParser
from datetime import datetime, timedelta
from time import mktime

import grequests
import requests
from requests.auth import HTTPBasicAuth


def parse_args():
    parser = ArgumentParser()
    parser.add_argument('--prefix', default='artfiles-uplink')
    parser.add_argument('-u', '--user', dest='username',
                        help='The http username to authenticate.')
    parser.add_argument('-p', '--pass', dest='password',
                        help='The http password to authenticate.')
    parser.add_argument('-m', '--minutes', type=int,
                        help='Just data from theis amount of minutes back in '
                             'time will be printed')
    parser.add_argument('-s', '--switches', nargs='*',
                        help='Just print data from these switches '
                             '(api id of the switches)')
    parser.add_argument('-v', '--verbose', action='count',
                        help='Verbose mode as counter '
                             '(1: info, 2: debug, ...)')
    return parser.parse_args()


def main():
    args = parse_args()

    if args.verbose:
        logging.basicConfig(level=(3 - args.verbose) * 10)
    else:
        logging.disable(logging.CRITICAL)

    logger = logging.getLogger('artfiles_uplink_traffic')

    filter_func = None
    if args.minutes:
        time_from = datetime.now() - timedelta(minutes=args.minutes)
        logger.debug(time_from)
        time_from = mktime(time_from.timetuple())
        logger.debug(time_from)

        def filter_func(timestamp):
            return timestamp >= time_from

    auth = None
    if args.username:
        auth = HTTPBasicAuth(args.username, args.password)

    switches = get_switches(auth)
    logger.info(switches)
    if args.switches:
        switches = [switch for switch in switches
                    if switch['id'] in args.switches]

    stat_requests = [
        get_traffic_stat_request(switch['id'], base=1, auth=auth)
        for switch in switches
        ]
    for request in stat_requests:
        logger.info(request.__dict__)

    responses = grequests.map(stat_requests)

    responses = zip(switches, responses)

    template = '{prefix}.{title}.{port}.{metric} {value} {time}'
    factors = {'Tbps': 1000000000000, 'Gbps': 1000000000, 'Mbps': 1000000,
               'Kbps': 1000, 'bps': 1}
    for switch, response in responses:
        if not response:
            logger.debug('No response: {}'.format(response.url))
            continue

        try:
            json_data = response.json()
        except ValueError as e:
            logger.warning('Error: %s', e)
            logger.warning('Strange Response:')
            logger.warning('URL: %s', response.url)
            logger.warning('Content:\n%s', response.content)
            continue

        logger.info(json_data)

        title = switch['switch'].replace('.', '_')
        port = switch['port'].replace(':', '_')

        template_params = {'prefix': args.prefix, 'title': title, 'port': port}

        parse_and_print_data(json_data.get('input'), 'bpsIn', factors,
                             filter_func, template, template_params)

        parse_and_print_data(json_data.get('output'), 'bpsOut', factors,
                             filter_func, template, template_params)


def get_switches(auth):
    scheme = 'https'
    host = 'dcp.c.artfiles.de'
    endpoint = 'api/stats/get_traffic.html'
    url = ('{scheme}://{host}/{endpoint}'
           .format(scheme=scheme, host=host, endpoint=endpoint))
    response = requests.get(url, auth=auth)

    return response.json()


def get_traffic_stat_request(switch_id, base=None, auth=None):
    scheme = 'https'
    host = 'dcp.c.artfiles.de'
    endpoint = 'api/stats/get_traffic.html'
    url = ('{scheme}://{host}/{endpoint}'
           .format(scheme=scheme, host=host, endpoint=endpoint))
    query = {'id': switch_id, 'si_base': base}
    request = grequests.get(url, params=query, auth=auth)

    return request


def parse_and_print_data(data, metric, factors=None, filter=None,
                         template=None, template_params=None):
    if template_params is None:
        template_params = {}

    if not factors:
        factors = {'Tbps': 1000000000000, 'Gbps': 1000000000, 'Mbps': 1000000,
                   'Kbps': 1000, 'Bps': 1}

    factor = parse_factor(
        data.get('meta').get('yValueFormatString'),
        factors
    )
    for traffic in data.get('data'):
        timestamp = int(traffic.get('x') / 1000)

        if not filter(timestamp):
            continue

        value = abs(traffic.get('y')) * factor
        print(template.format(
            metric=metric, value=value, time=timestamp, **template_params)
        )


def parse_factor(factor_string, factor_table):
    template, factor = factor_string.split()

    return factor_table.get(factor)


if __name__ == '__main__':
    main()