package kz.cafe.security;

import java.util.*;
import java.util.concurrent.locks.*;
import org.apache.commons.logging.*;
import kz.cafe.exceptions.*;

public final class Sessions{
   private static Log log = LogFactory.getLog(Sessions.class);

   private static final String LOG = "[SESSIONS] ";
   
   
   //SESSION, UID
   public static final Map<Long, Integer> mapS2U = new HashMap<Long, Integer>();
   
   //UID, SESSION
   public static final Map<Integer, Long> mapU2S = new HashMap<Integer, Long>();
   
   
   
   private static final ReentrantLock LOCK = new ReentrantLock(); 


   
   
   public static long open(int UID){
      log.info(LOG + "Let's open a new session for UID=" + UID);
      
      closeSessionUID(UID);
      
      LOCK.lock();
      try{
         while(true){
            long SID = (long) (Math.random() * Long.MAX_VALUE);
            
            if(mapS2U.containsKey(SID)){
               continue;
            }
            
            mapS2U.put(SID, UID);
            mapU2S.put(UID, SID);
            
            log.info(LOG + "UID=" + UID + " now runs the SID=" + SID);
            
            return SID;
         }
      }
      finally{
         LOCK.unlock();
      }
   }
   

   
   
   
   
   
   
   public static int getUID(long SID) throws AbstractSecurityException{
      LOCK.lock();

      try{
         Integer UID = mapS2U.get(SID);

         if(UID == null){
            throw new SessionNotFoundException("" + SID);
         }
         
         log.debug(LOG + "SID=" + SID + " is UID=" + UID);

         return UID;
      }
      finally{
         LOCK.unlock();
      }
   }
   
   
   
   
   
   public static void closeSessionSID(long SID){
      LOCK.lock();

      try{
         Integer UID = mapS2U.get(SID);
         
         mapS2U.remove(SID);
         mapU2S.remove(UID);
      }
      finally{
         LOCK.unlock();
      }
   }
   public static void closeSessionUID(long UID){
      LOCK.lock();

      try{
         Long SID = mapU2S.get(UID);
         
         mapS2U.remove(SID);
         mapU2S.remove(UID);
      }
      finally{
         LOCK.unlock();
      }
   }
}
