# coding=utf-8

from rest_framework.throttling import SimpleRateThrottle
from django.conf import settings


class CustomRateThrottle(SimpleRateThrottle):
    def allow_request(self, request, view):
        """
        Implement the check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        """
        if not settings.IS_THROTTLE:
            return True

        if self.rate is None:
            return True

        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True

        self.history = self.cache.get(self.key, [])
        self.now = self.timer()

        # Drop any requests from the history which have now passed the
        # throttle duration
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop()
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()

    def get_cache_key(self, request, view):
        if request.user.is_authenticated:
            ident = request.user.id
        else:
            ident = self.get_ident(request)

        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }

    def parse_rate(self, rate):
        """
        Given the request rate string, return a two tuple of:
        <allowed number of requests>, <period of time in seconds>
        """
        if rate is None:
            return None, None
        num, period = rate.split('/')
        period_digit, period = period.split('*')
        num_requests = int(num)
        duration = int(period_digit) * {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
        return num_requests, duration


class ManuallyUpdateCacheThrottle(CustomRateThrottle):
    scope = 'manually_update_cache'

    def throttle_success(self):
        """
        Inserts the current request's timestamp along with the key
        into the cache.
        """
        return True

    def throttle_failure(self):
        """
        Called when a request to the API has failed due to throttling.
        """
        return False

    def throttle_success_update_cache(self, request, view):
        """
        Manually update cache
        """
        self.key = self.get_cache_key(request, view)
        self.history = self.cache.get(self.key, [])
        self.now = self.timer()
        if self.history:
            self.cache.set(self.key, [], self.duration)

    def throttle_failure_update_cache(self, request, view):
        """
        Manually update cache
        """
        self.key = self.get_cache_key(request, view)
        self.history = self.cache.get(self.key, [])
        self.now = self.timer()
        self.history.insert(0, self.now)
        self.cache.set(self.key, self.history, self.duration)


class APIRateThrottle(CustomRateThrottle):
    scope = 'api'
