package kz.cafe.cache;

import java.lang.reflect.*;
import java.util.*;
import kz.cafe.db.*;
import kz.cafe.db.model.*;

public class OnePassCache{

   public Map<Class<?>, Map<Integer, Map<String, Object>>> map = new HashMap<Class<?>, Map<Integer, Map<String, Object>>>();
   
   Set<String> setReloadHash = new HashSet<String>();



   public OnePassCache(){
   }


   
   
   



   public Object getValue(Class<?> classs, int ID, String sField){

      Map<Integer, Map<String, Object>> mapData = map.get(classs);

      if(mapData == null){
         reload(classs, ID, sField);
         mapData = map.get(classs);
      }


      Map<String, Object> mapObject = mapData.get(ID);

      if(mapObject == null){
         reload(classs, ID, sField);
         mapObject = mapData.get(ID);
      }

      Object obj = map.get(sField);
      
      String sCacheHash = classs.getName() + "_" + ID + "_" + sField;

      if(obj == null && setReloadHash.contains(sCacheHash)){
         
         return null;
      }
      else{
         reload(classs, ID, sField);
         setReloadHash.add(sCacheHash);
         
         return mapObject.get(sField);
      }
   }





   private void reload(Class<?> classs, int ID, String sField){

      Map<Integer, Map<String, Object>> mapData = map.get(classs);

      if(mapData == null){
         mapData = new HashMap<Integer, Map<String, Object>>();
         map.put(classs, mapData);
      }


      for(Object obj : MongoService.ds.find(classs).retrievedFields(true, MAbstractDataElement.F_ID, sField).asList()){
         MAbstractDataElement mAbstractDataElement = (MAbstractDataElement) obj;
         Map<String, Object> mapObject = mapData.get(mAbstractDataElement.ID);

         if(mapObject == null){
            mapObject = new HashMap<String, Object>();
            mapData.put(mAbstractDataElement.ID, mapObject);
         }

         try{
            Field field = classs.getField(sField);
            field.setAccessible(true);
            mapObject.put(sField, field.get(obj));
         }
         catch (Exception e){
            throw new Error("Can not cache Element", e);
         }
      }
   }
}
