import time
from threading import Thread

from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.models import AnonymousUser
from rest_framework import generics
from rest_framework import status
from rest_framework.response import Response

from common.sessions.cache import user_session_manager
from common.utils import get_logger

__all__ = ['UserSessionApi']

logger = get_logger(__name__)


class UserSessionManager:

    def __init__(self, request):
        self.request = request
        self.session = request.session

    def connect(self):
        user_session_manager.add_or_increment(self.session.session_key)

    def disconnect(self):
        user_session_manager.decrement(self.session.session_key)
        if self.should_delete_session():
            thread = Thread(target=self.delay_delete_session)
            thread.start()

    def should_delete_session(self):
        return (self.session.modified or settings.SESSION_SAVE_EVERY_REQUEST) and \
            not self.session.is_empty() and \
            self.session.get_expire_at_browser_close() and \
            not user_session_manager.check_active(self.session.session_key)

    def delay_delete_session(self):
        timeout = 6
        check_interval = 0.5

        start_time = time.time()
        while time.time() - start_time < timeout:
            time.sleep(check_interval)
            if user_session_manager.check_active(self.session.session_key):
                return

        logout(self.request)


class UserSessionApi(generics.RetrieveDestroyAPIView):
    permission_classes = ()

    def retrieve(self, request, *args, **kwargs):
        if isinstance(request.user, AnonymousUser):
            return Response(status=status.HTTP_403_FORBIDDEN)

        UserSessionManager(request).connect()
        return Response(status=status.HTTP_200_OK, data={'ok': True})

    def destroy(self, request, *args, **kwargs):
        if isinstance(request.user, AnonymousUser):
            return Response(status=status.HTTP_403_FORBIDDEN)

        UserSessionManager(request).disconnect()
        return Response(status=status.HTTP_200_OK, data={'ok': True})
