package electrosphere.client.fluid.cache;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;


/**
 * Acts as a cache in front of fluid model to streamline receiving chunks
 */
public class ClientFluidCache {
    
    //cache capacity
    int cacheSize;
    //the map of chunk key -> chunk data
    Map<String,FluidChunkData> cacheMap = new ConcurrentHashMap<String,FluidChunkData>();
    //the list of keys in the cache
    List<String> cacheList = new CopyOnWriteArrayList<String>();
    
    /**
     * Constructor
     * @param cacheSize The capacity of the cache
     */
    public ClientFluidCache(int cacheSize){
        this.cacheSize = cacheSize;
    }
    
    /**
     * Adds a chunk data to the fluid cache
     * @param worldX The x world position
     * @param worldY The y world position
     * @param worldZ The z world position
     * @param chunkData The chunk data to add at the specified positions
     */
    public void addChunkDataToCache(int worldX, int worldY, int worldZ, FluidChunkData chunkData){
        cacheMap.put(getKey(worldX,worldY,worldZ),chunkData);
        while(cacheList.size() > cacheSize){
            String currentChunk = cacheList.remove(0);
            cacheMap.remove(currentChunk);
        }
    }
    
    
    /**
     * Generates a key for the cache based on the position provided
     * @param worldX The x world position
     * @param worldY The y world position
     * @param worldZ The z world position
     * @return The cache key
     */
    public String getKey(int worldX, int worldY, int worldZ){
        return worldX + "_" + worldY + "_" + worldZ;
    }
    
    /**
     * Checks whether the cache contains chunk data at a given world point
     * @param worldX The x world position
     * @param worldY The y world position
     * @param worldZ The z world position
     * @return True if the cache contains chunk data at the specified point, false otherwise
     */
    public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
        return cacheMap.containsKey(getKey(worldX,worldY,worldZ));
    }
    
    
    
    
    
    /**
     * Gets chunk data at the given world point
     * @param worldX The x world position
     * @param worldY The y world position
     * @param worldZ The z world position
     * @return The chunk data if it exists, null otherwise
     */
    public FluidChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ){
        return cacheMap.get(getKey(worldX,worldY,worldZ));
    }
    
}
