import abc

from flask import request, jsonify
from redis import RedisError
import pymongo

from jobs import process_event_data


class BaseHandler(object):
    """
    Base class for request handlers.
    """

    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def view_name(self):
        """
        Implement to return the Flask view name for this handler.
        """
        raise NotImplementedError()

    @abc.abstractproperty
    def methods(self):
        """
        Implement to return the methods supported by this handler.
        """
        raise NotImplementedError()

    @abc.abstractmethod
    def handle(self, *args, **kwargs):
        """
        Implement to handle the request.
        """


class EventPushHandler(BaseHandler):
    """
    Handles event submitting endpoint.
    """

    view_name = 'push_event'
    methods = ['POST']

    def handle(self):
        """
        Pushes event to the task queue.
        """
        username = request.headers.get('User.Username')
        permission = request.headers.get('User.Permission')

        if permission is None or int(permission) > 1:
            return jsonify({'error': 'not allowed'}), 409

        data = {
            'author': username,
            'input': request.json['input'],
        }
        try:
            process_event_data.delay(data)
            return jsonify({'success': True})
        except RedisError:
            return jsonify({'success': False})


class GetEventsHandler(BaseHandler):
    """
    Handles endpoint for getting the events for a user.
    """

    view_name = 'get_events'
    methods = ['GET']

    EVENT_OUTPUT_FIELDS = [
        'created_at',
        'user_id',
        'properties',
        'rule',
        'author',
        'input',
    ]

    PREDICTED_EVENT_OUTPUT_FIELDS = [
        'created_at',
        'user_id',
        'properties',
        'rule',
        'author',
        'prob',
    ]

    def __init__(self, mongo):
        """
        @param mongo: mongo client
        """
        self.mongo = mongo

    def handle(self):
        """
        Fetches events for the user id given in the headers.
        """
        # TODO: Handle errors
        user_id = request.headers.get('User.Username')

        if user_id is None:
            return jsonify([])

        query = {'$or': [{'user_id': user_id}, {'author': user_id}]}
        cursor = self.mongo.db.events.find(query).sort('created_at', pymongo.DESCENDING)
        events = []
        predicted = None
        for event in cursor:
            if event.get('predicted', False):
                assert not predicted
                predicted = {f: event[f] for f in self.PREDICTED_EVENT_OUTPUT_FIELDS}
            else:
                events.append({f: event[f] for f in self.EVENT_OUTPUT_FIELDS})

        return jsonify({'predicted': predicted, 'eventlog': events})

@@ -2243,16 +2243,81 @@
 ername')
+%0A        permission = int(request.headers.get('User.Permission'))
 %0A%0A      
@@ -2382,67 +2382,232 @@
     
-query = %7B'$or': %5B%7B'user_id': user_id%7D, %7B'author': user_id%7D%5D
+# Want to find events that the user authored or was tagged in.%0A        query = %7B'$or': %5B%7B'user_id': user_id%7D, %7B'author': user_id%7D%5D%7D%0A        if permission == 0:%0A            # Sysadmin can see everything.%0A            query = %7B
 %7D%0A  
@@ -2733,20 +2733,18 @@
 icted = 
-None
+%5B%5D
 %0A       
@@ -2831,57 +2831,25 @@
     
-assert not predicted%0A                predicted = 
+predicted.append(
 %7Bf: 
@@ -2901,16 +2901,17 @@
 _FIELDS%7D
+)
 %0A       

Return all events for sysadmins