from typing import Dict
import time
import threading, asyncio

from qwin_bot_domain import QwinBotConversationContext

class SessionDict:
    def __init__(self, 
                 sessions_live_timeout: int=5, 
                 sessions_clear_timeout: int=30, 
                 verbose: bool=False):
        
        
        self.data: Dict[str: QwinBotConversationContext] = {}
        
        self.sessions_live_timeout = sessions_live_timeout * 60
        self.sessions_clear_timeout = sessions_clear_timeout * 60
        self.lock = threading.Lock()
        
        self.loop = asyncio.new_event_loop()
        self.thread = threading.Thread(target=self.start_loop(verbose=verbose))
        self.thread.daemon = True
        self.thread.start()
        
    def set(self, key: str, value: QwinBotConversationContext):
        with self.lock:
            self.data[key] = {
                'value': value,
                'expriration_time': time.time() + self.sessions_live_timeout
            }
            
    def get(self, key: str) -> QwinBotConversationContext:
        with self.lock:
            if key in self.data:
                item = self.data[key]
                if time.time() < item['expriration_time']:
                    item['expriration_time'] = time.time() + self.sessions_live_timeout
                    return item['value']
                else:
                    del self.data[key]
                    
            return None
        
    def remove(self, key: str):
        with self.lock:
            if key in self.data:
                del self.data[key]
                
    def clear_expired(self, verbose: bool=False):
        with self.lock:
            for key in list(self.data.keys()):
                item = self.data[key]
                if time.time() >= item['expriration_time']:
                    del self.data[key]
                    if verbose:
                        print(f'Session for user {key} removed')
                        
    async def clear_session(self, verbose: bool=False):
        while True:
            if verbose:
                print('Sessions cleaning started ...')
            self.clear_expired(verbose=verbose)
            await asyncio.sleep(self.sessions_clear_timeout)
                        
    def start_loop(self, verbose=False):
        def clear_fn():
            asyncio.set_event_loop(self.loop)
            self.loop.run_until_complete(self.clear_session(verbose=verbose))
        return clear_fn

