#!/usr/bin/python
# -*- coding: utf-8 -*-

from ceilometerclient import client
from os import environ as env
import keystoneclient.v2_0.client as ksclient
import re
import datetime
import time
from monitor.monitordriver import *


def cli_to_array(cli_query):
    '''This converts from the cli list of queries to what is required
    by the python api.
    so from:
    "this<=34;that=foo"
    to
    "[{field=this,op=le,value=34},{field=that,op=eq,value=foo}]"
    '''
    if cli_query is None:
        return None

    op_lookup = {'!=': 'ne',
                 '>=': 'ge',
                 '<=': 'le',
                 '>': 'gt',
                 '<': 'lt',
                 '=': 'eq'}

    def split_by_op(string):
        # two character split (<=,!=)
        frags = re.findall(r'([[a-zA-Z0-9_.]+)([><!]=)([^ -,\t\n\r\f\v]+)',
                           string)
        if len(frags) == 0:
            #single char split (<,=)
            frags = re.findall(r'([a-zA-Z0-9_.]+)([><=])([^ -,\t\n\r\f\v]+)',
                               string)
        return frags

    opts = []
    queries = cli_query.split(';')
    for q in queries:
        frag = split_by_op(q)
        if len(frag) > 1:
            raise ValueError('incorrect seperator %s in query "%s"' %
                             ('(should be ";")', q))
        if len(frag) == 0:
            raise ValueError('invalid query %s' % q)
        query = frag[0]
        opt = {}
        opt['field'] = query[0]
        opt['op'] = op_lookup[query[1]]
        opt['value'] = query[2]
        opts.append(opt)
    return opts

def meters_to_stats(meters):
    stats = DashboardStatistics()
    for m in meters:
        timestamp = datetime.datetime.strptime(m.duration_start,'%Y-%m-%dT%H:%M:%S')
        stats.stat_list.append({'timestamp':timestamp, 'value':m.sum})
        stats.sum+=m.sum
        stats.average+=m.sum
        stats.unit = 'ns'

    stats.average/=len(meters)
    return stats
        
                

class CeilometerDriver(MonitorDriver):
    def get_meter(self, meter, object_filter, keystone):
        if (not keystone):
            keystone = {}
            keystone['username']=env['OS_USERNAME']
            keystone['password']=env['OS_PASSWORD']
            keystone['auth_url']=env['OS_AUTH_URL']
            keystone['tenant_name']=env['OS_TENANT_NAME']

        ceilometer_client = client._get_ksclient(**keystone)
        token = ceilometer_client.auth_token

        ceilo_endpoint = client._get_endpoint(ceilometer_client, **keystone)

        ceilometer = client.Client('2',endpoint = ceilo_endpoint, token = lambda: token)

        cur_ts = datetime.datetime.fromtimestamp(time.time()-86400)
        str_ts = cur_ts.strftime('%Y-%m-%dT%H:%M:%S')
        
        filter=';'.join([object_filter,'timestamp>%s'%str_ts])
        #query = cli_to_array("project_id=124de34266b24f57957345cdb43cc9ff;timestamp>2014-12-11T00:00:00")
        query = cli_to_array(filter)

        meters = ceilometer.statistics.list(meter,q=query,period=3600)

        stats = meters_to_stats(meters)
        return stats

