from rest_framework.throttling import BaseThrottle
from throttle.models import ListModel
from utils.md5 import Md5
from django.utils import timezone
from django.conf import settings

data = {}

class VisitThrottle(BaseThrottle):
    def allow_request(self, request, view):
        if request.path in ['/api/docs/', '/api/debug/', '/api/']:
            return (False, None)
        elif request.path in ['/container/container_wcs/','/container/container_wcs/update/','/container/location_release/',
                                '/container/batch/','/wms/createInboundApply','/wms/createOutboundApply'
                                ,'/wms/productInfo','/wms/updateBatchInfo']:
            return True
        else:
            ip = request.META.get('HTTP_X_FORWARDED_FOR') if request.META.get(
                'HTTP_X_FORWARDED_FOR') else request.META.get('REMOTE_ADDR')
            openid = request.auth.openid
            appid = request.auth.appid
            if request.method.lower() == "get":
                ntime = timezone.now()
                ctime = ntime - timezone.timedelta(seconds=1)
                throttle_ctimelist = ListModel.objects.filter(method="get", create_time__lte=ctime)
                for i in throttle_ctimelist:
                    i.delete()
                t_code = Md5.md5(ip)
                throttle_allocationlist = ListModel.objects.filter(openid=openid, appid=appid, ip=ip,
                                                                   method='get').order_by('id')
                throttle_count = throttle_allocationlist.count()
                if throttle_count == 0:
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="get", t_code=t_code)
                    return True
                else:
                    throttle_last_create_time = throttle_allocationlist.first().create_time
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="get", t_code=t_code)
                    allocation_seconds_balance = (ntime - throttle_last_create_time).seconds
                    data["visit_check"] = throttle_last_create_time
                    if allocation_seconds_balance >= settings.ALLOCATION_SECONDS:
                        return True
                    else:
                        if throttle_count >= settings.GET_THROTTLE:
                            return False
                        else:
                            return True
            elif request.method.lower() == "post":
                ntime = timezone.now()
                ctime = ntime - timezone.timedelta(seconds=1)
                throttle_ctimelist = ListModel.objects.filter(method="post", create_time__lte=ctime)
                for i in throttle_ctimelist:
                    i.delete()
                t_code = Md5.md5(ip)
                throttle_allocationlist = ListModel.objects.filter(openid=openid, appid=appid, ip=ip,
                                                                   method='post').order_by('id')
                throttle_count = throttle_allocationlist.count()
                if throttle_count == 0:
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="post", t_code=t_code)
                    return True
                else:
                    throttle_last_create_time = throttle_allocationlist.first().create_time
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="post", t_code=t_code)
                    allocation_seconds_balance = (ntime - throttle_last_create_time).seconds
                    data["visit_check"] = throttle_last_create_time
                    if allocation_seconds_balance >= settings.ALLOCATION_SECONDS:
                        return True
                    else:
                        if throttle_count >= settings.POST_THROTTLE:
                            return False
                        else:
                            return True
            elif request.method.lower() == "put":
                ntime = timezone.now()
                ctime = ntime - timezone.timedelta(seconds=1)
                throttle_ctimelist = ListModel.objects.filter(method="put", create_time__lte=ctime)
                for i in throttle_ctimelist:
                    i.delete()
                t_code = Md5.md5(ip)
                throttle_allocationlist = ListModel.objects.filter(openid=openid, appid=appid, ip=ip,
                                                                   method='put').order_by('id')
                throttle_count = throttle_allocationlist.count()
                if throttle_count == 0:
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="put", t_code=t_code)
                    return True
                else:
                    throttle_last_create_time = throttle_allocationlist.first().create_time
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="put", t_code=t_code)
                    allocation_seconds_balance = (ntime - throttle_last_create_time).seconds
                    data["visit_check"] = throttle_last_create_time
                    if allocation_seconds_balance >= settings.ALLOCATION_SECONDS:
                        return True
                    else:
                        if throttle_count >= settings.PUT_THROTTLE:
                            return False
                        else:
                            return True
            elif request.method.lower() == "patch":
                ntime = timezone.now()
                ctime = ntime - timezone.timedelta(seconds=1)
                throttle_ctimelist = ListModel.objects.filter(method="patch", create_time__lte=ctime)
                for i in throttle_ctimelist:
                    i.delete()
                t_code = Md5.md5(ip)
                throttle_allocationlist = ListModel.objects.filter(openid=openid, appid=appid, ip=ip,
                                                                   method='patch').order_by('id')
                throttle_count = throttle_allocationlist.count()
                if throttle_count == 0:
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="patch", t_code=t_code)
                    return True
                else:
                    throttle_last_create_time = throttle_allocationlist.first().create_time
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="patch", t_code=t_code)
                    allocation_seconds_balance = (ntime - throttle_last_create_time).seconds
                    data["visit_check"] = throttle_last_create_time
                    if allocation_seconds_balance >= settings.ALLOCATION_SECONDS:
                        return True
                    else:
                        if throttle_count >= settings.PATCH_THROTTLE:
                            return False
                        else:
                            return True
            elif request.method.lower() == "delete":
                ntime = timezone.now()
                ctime = ntime - timezone.timedelta(seconds=1)
                throttle_ctimelist = ListModel.objects.filter(method="delete", create_time__lte=ctime)
                for i in throttle_ctimelist:
                    i.delete()
                t_code = Md5.md5(ip)
                throttle_allocationlist = ListModel.objects.filter(openid=openid, appid=appid, ip=ip,
                                                                   method='delete').order_by('id')
                throttle_count = throttle_allocationlist.count()
                if throttle_count == 0:
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="delete", t_code=t_code)
                    return True
                else:
                    throttle_last_create_time = throttle_allocationlist.first().create_time
                    ListModel.objects.create(openid=openid, appid=appid, ip=ip, method="delete", t_code=t_code)
                    allocation_seconds_balance = (ntime - throttle_last_create_time).seconds
                    data["visit_check"] = throttle_last_create_time
                    if allocation_seconds_balance >= settings.ALLOCATION_SECONDS:
                        return True
                    else:
                        if throttle_count >= settings.DELETE_THROTTLE:
                            return False
                        else:
                            return True
            else:
                return False

    def wait(self):
        ctime = timezone.now()
        wait_time = (ctime - data["visit_check"]).seconds
        balance_time = 1 - wait_time
        return balance_time