"""
sentry.rules.conditions.event_frequency
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from __future__ import absolute_import

from datetime import datetime, timedelta
from django import forms
from pytz import utc

from django.utils import timezone
from sentry.rules.conditions.base import EventCondition


class Interval(object):
    ONE_MINUTE = '1m'
    ONE_HOUR = '1h'


class EventFrequencyForm(forms.Form):
    interval = forms.ChoiceField(choices=(
        (Interval.ONE_MINUTE, 'one minute'),
        (Interval.ONE_HOUR, 'one hour'),
    ))
    value = forms.IntegerField(widget=forms.TextInput(attrs={
        'placeholder': '100',
        'type': 'number'
    }))


class EventFrequencyCondition(EventCondition):
    form_cls = EventFrequencyForm
    label = 'An event is seen more than {value} times in {interval}'

    def __init__(self, *args, **kwargs):
        from sentry.app import tsdb

        self.tsdb = kwargs.pop('tsdb', tsdb)

        super(EventFrequencyCondition, self).__init__(*args, **kwargs)

    def passes(self, event, state):
        # when a rule is not active (i.e. it hasnt gone from inactive -> active)
        # it means that we already notified the user about this condition and
        # shouldn't spam them again
        if state.rule_is_active:
            return False

        interval = self.get_option('interval')
        try:
            value = int(self.get_option('value'))
        except (TypeError, ValueError):
            return False

        if not (interval and value):
            return False

        now = timezone.now()

        # XXX(dcramer): hardcode 30 minute frequency until rules support choices
        if state.rule_last_active and state.rule_last_active > (now - timedelta(minutes=30)):
            return False

        current_value = self.get_rate(event, interval)

        return current_value > value

    def clear_cache(self, event):
        event._rate_cache = {}

    def get_rate(self, event, interval):
        if not hasattr(event, '_rate_cache'):
            event._rate_cache = {}

        result = event._rate_cache.get(interval)
        if result is None:
            end = datetime.utcnow().replace(tzinfo=utc)
            if interval == Interval.ONE_MINUTE:
                start = end - timedelta(minutes=1)
            elif interval == Interval.ONE_HOUR:
                start = end - timedelta(hours=1)
            else:
                raise ValueError(interval)

            result = self.tsdb.get_sums(
                model=self.tsdb.models.group,
                keys=[event.group_id],
                start=start,
                end=end,
            )[event.group_id]
            event._rate_cache[interval] = result

        return result
