package org.wikiwebserver.core;

import java.util.Iterator;
import java.util.Map;

public class WikiCache {
        
    private static final long serialVersionUID = 1l;  
    
    private static final int CACHE_PURGE_DELAY = ConfigManager.getInt("wiki-cache-purge-delay");     
    
    private final Object cacheLock = new Object();      
    private final WikiCacheMap wikiCacheMap = new WikiCacheMap();

    private boolean enabled = true;
    private long lastCachePurgeTime = System.currentTimeMillis();
    
    public void clear() {
        synchronized (cacheLock) {
            wikiCacheMap.clear();
        }
    }
        
    public void setEnabled(boolean on) {
        this.enabled = on;
        if (!enabled) clear();
    }
    
    public WikiCacheItem lookup(String key) {
        
        if (!enabled) return null;
        
        WikiCacheItem cachedItem = null;
        long time = System.currentTimeMillis();        
        synchronized (cacheLock) {
            cachedItem = wikiCacheMap.get(key);
            if (cachedItem != null && time > cachedItem.getExpireTime()) {
                cachedItem = null;
                wikiCacheMap.remove(key);
            }            
        }  
      
        return cachedItem;
    }
    
    public void store(String key, WikiCacheItem item) {
        
        if (!enabled) return;
        
        synchronized (cacheLock) {
            wikiCacheMap.put(key, item);
        }
        cleanup();
    }
    
    public long getSizeInBytes() {
        synchronized (cacheLock) {
            return wikiCacheMap.sizeInBytes();
        }
    }    

    public int size() {
        synchronized (cacheLock) {
            return wikiCacheMap.size();
        }
    }
    
    private void cleanup() {
        
        long time = System.currentTimeMillis();
        
        // Purge expired items from the cache        
        if (time > lastCachePurgeTime + CACHE_PURGE_DELAY) {
            synchronized (cacheLock) {
                if (time > lastCachePurgeTime + CACHE_PURGE_DELAY) {
                    lastCachePurgeTime = time;         
    
                    Iterator<Map.Entry<String, WikiCacheItem>> i = wikiCacheMap.entrySet().iterator();
                    while (i.hasNext()) {
                        Map.Entry<String, WikiCacheItem> entry = i.next();
                        if (time > entry.getValue().getExpireTime()) {
                            i.remove();
                        }
                    }
                }
            }
        }
    }    
}

