#!/usr/bin/python3
# coding=utf-8

"""Collect metrics from multiple services and push them to InfluxDB."""

# Libraries
import json
import os
import sys
import time
from urllib.parse import urlparse
from influxdb import InfluxDBClient
from etherpad import EtherpadCollector
from mattermost import MattermostCollector
from wekan import WekanCollector

# Some constants
DIR_NAME = os.path.dirname(os.path.realpath(__file__))
CONFIG_FILE = os.path.join(DIR_NAME, 'config/config.json')


def influxb_connect(config):
    """
    Instanciate a client for InfluxDB.
    :param config: Configuration for InfluxDB
    :returns: InfluxDBClient object
    """
    # Check configuration file
    if 'url' not in config and 'database' not in config:
        print('You need to add influxdb URL and database to configuration file.')
        sys.exit(1)

    # Parse influx connection string
    o = urlparse(config['url'])
    if o.port is None:
        if o.scheme == 'https':
            port = 443
            ssl = True
        elif o.scheme == 'http':
            port = 80
            ssl = False
        else:
            port = 8086
            ssl = False
    else:
        port = o.port
        ssl = bool(o.scheme == 'https')
    verify = bool(ssl)

    # Connect to influx db
    try:
        if 'user' in config and 'password' in config:
            # Influx authentication enabled
            client = InfluxDBClient(
                host=o.hostname,
                port=port,
                username=config['user'],
                password=config['password'],
                database=config['database'],
                ssl=ssl,
                verify_ssl=verify
            )
        else:
            # Influx authentication disabled
            client = InfluxDBClient(
                host=o.hostname,
                port=port,
                database=config['database'],
                ssl=ssl,
                verify_ssl=verify
            )
        client.ping()
        return client
    except KeyError as e:
        if e.args == ("x-influxdb-version",):
            print("Ignoring vmagent missing x-influxdb-version header")
        return client
    except Exception as e:
        print("Cannot connect to {} : {}".format(o.hostname, e))
        print("If InfluxDB has just started, this is normal, please wait!")
        return None


def main():
    """Run main function."""
    # Load configuration file
    try:
        with open(CONFIG_FILE, 'r') as fd:
            config = json.load(fd)
    except Exception as e:
        print('Error when reading configuration file')
        print(e)
        sys.exit(1)

    # Get connector for InfluxDB
    if 'influxdb' not in config:
        print('You need to add InfluxDB configuration on your config file.')
        sys.exit(1)
    influx_client = influxb_connect(config['influxdb'])
    while influx_client is None:
        print("InfluxDB not available, retrying in 5 seconds...")
        time.sleep(5)
        influx_client = influxb_connect(config['influxdb'])

    # Get Etherpad metrics and push to InfluxDB
    if 'etherpad' in config['modules']:
        etherpad = EtherpadCollector(config['modules']['etherpad'])
        etherpad_data = etherpad.collect()
        influx_client.write_points(etherpad_data, 'ms')

    # Get Mattermost metrics and push to InfluxDB
    if 'mattermost' in config['modules']:
        mattermost = MattermostCollector(config['modules']['mattermost'])
        mattermost_data = mattermost.collect()
        influx_client.write_points(mattermost_data, 'ms')

    # Get Wekan metrics and push to InfluxDB
    if 'wekan' in config['modules']:
        wekan = WekanCollector(config['modules']['wekan'])
        wekan_data = wekan.collect()
        influx_client.write_points(wekan_data, 'ms')


if __name__ == "__main__":
    main()