import requests
import json
from server_modules.util import *

def get_info(easydb_context, db_cursor, config, instance, loggername):
    eas_url = get_config(config, 'system/eas/url')
    eas_instance = get_config(config, 'system/eas/instance')
    eas_produce_md5 = instance['eas_produce_md5']
    parts = [
        get_general_information(eas_url, eas_instance),
        get_queue_stats(db_cursor, eas_produce_md5),
    ]
    try:
        eas_config = get_eas(eas_url, eas_instance, 'config')
        parts.append(get_eas_config_info(eas_config))

        eas_info = get_eas(eas_url, eas_instance, 'status')
        parts.append(get_eas_partitions(eas_info))
        parts.append(get_eas_queue_stats(eas_info))
    except Exception as e:
        parts.append(make_error('connect-error', 'error.server.connect', str(e)))
    return parts

def get_general_information(eas_url, eas_instance):
    data = [
        make_data('string', 'server-url', eas_url),
        make_data('string', 'instance', eas_instance)
    ]
    return make_map('general', data)

def get_eas_config_info(eas_config):
    data = [
        make_data('string', 'package-version', eas_config.get('package_version', '')),
        make_data('integer', 'num-workers', eas_config.get('EAS_NUM_WORKERS', 0)),
    ]

    # FIXME: EAS returns null if not explicitly configured
    #        (default of 2 is used internally)
    n_soffice = eas_config.get('EAS_NUM_SOFFICE', 0)
    if n_soffice is not None:
        data.append(make_data('integer', 'num-soffice', n_soffice))

    return make_map('config', data)

def get_queue_stats(db_cursor, eas_produce_md5):
    versions = ['new', 'changed', 'current']
    counts = [0, 0, 0]
    db_cursor.execute('select produce_conf_md5, count(*) from ez_assets group by 1')
    rows = db_cursor.fetchall()
    for row in rows:
        count = int(row['count'])
        pcmd5 = row['produce_conf_md5']
        if pcmd5 is None:
            counts[0] = count
        elif pcmd5 == eas_produce_md5:
            counts[2] = count
        else:
            counts[1] = count
    data = [
        make_data('integer', 'count', counts)
    ]
    return make_table('produce_info', 'version', versions, data)

def get_eas(eas_url, eas_instance, api):
    r = requests.get('{0}/{1}'.format(eas_url, api), params={'instance': eas_instance})
    if r.status_code != 200:
        raise Exception('EAS {2} request returned {0}: {1}'.format(r.status_code, r.text, api))
    try:
        return json.loads(r.text)
    except Exception as e:
        raise Exception('Could not parse EAS {1} response: {0}'.format(str(e), api))

def get_eas_partitions(eas_info):
    try:
        partitions = eas_info['partitions']
        names = [p['name'] for p in partitions]
        free_values = [p['free'] for p in partitions]
        used_values = [p['used'] for p in partitions]
        total_values = [x + y for x, y in zip(free_values, used_values)]
        fill_values = [100.0 * x / y for x, y in zip(used_values, total_values)]
        data = [
            make_data('integer', 'number', [p['id'] for p in partitions]),
            make_data('string', 'path', [p['path'] for p in partitions]),
            make_data('integer', 'free', free_values, 'bytes'),
            make_data('integer', 'total', total_values, 'bytes'),
            make_data('float', 'fill', fill_values, 'completion'),
            make_data('boolean', 'disabled', [p['disabled'] for p in partitions]),
            make_data('date', 'auto-disabled-at', [p['auto_disabled_at'] for p in partitions])
        ]
        return make_table('partitions', 'partition-name', names, data)
    except Exception as e:
        raise Exception('Could not parse EAS status response: {0}'.format(str(e)))

def get_eas_queue_stats(eas_info):
    try:
        status = []
        counts = []
        _recent_jobs = 0
        _pending = 0
        for k, v in list(eas_info['jobs'].items()):
            status.append(k)
            counts.append(v)
            if k == 'recent-done' or k == 'recent-failed':
                if isinstance(v, int) and v > 0:
                    _recent_jobs += v
            elif k == 'pending':
                if isinstance(v, int) and v > 0:
                    _pending = v

        if _recent_jobs > 0:
            status.append('time-per-job')
            _t_per_job = 86400 / _recent_jobs # time per job in seconds (average over last 24 hours)
            counts.append(_t_per_job)

            if _pending > 0:
                status.append('est-time-left')
                counts.append(_t_per_job * _pending)

        data = [
            make_data('integer', 'count', counts)
        ]
        return make_table('queue', 'status', status, data)
    except Exception as e:
        raise Exception('Could not parse EAS status response: {0}'.format(str(e)))
