package electrosphere.game.client.terrain.cache;

import electrosphere.game.client.world.ClientWorldData;
import electrosphere.game.server.terrain.models.TerrainModel;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class ClientTerrainCache {
    
    /*
    Acts as a cache in front of terrain model to streamline receiving heightmaps
    on both client and server
    */
    
    
    
    ClientWorldData clientWorldData;
    
    
    int cacheSize;
    ConcurrentHashMap<String,float[][]> cacheMap = new ConcurrentHashMap();
    CopyOnWriteArrayList<String> cacheList = new CopyOnWriteArrayList();
    
    
    public ClientTerrainCache(int cacheSize, ClientWorldData clientWorldData){
        this.cacheSize = cacheSize;
        this.clientWorldData = clientWorldData;
    }
    
//    TerrainChunkValues getChunkValuesAtPoint(int x, int y){
//        if(terrainModel != null){
//            return new TerrainChunkValues(
//                terrainModel.getMacroValuesAtPosition(x, y),
//                terrainModel.getRandomizerValuesAtPosition(x, y)
//            );
//        } else {
//            return new TerrainChunkValues(
//                    new float[3][3],
//                    new long[3][3]
//            );
//        }
//    }
    
    
    //USED TO ADD macro values
    public void addChunkValuesToCache(int x, int y, float[][] macroValues, long[][] randomizer){
//        TerrainChunkValues chunk = new TerrainChunkValues(macroValues, randomizer);
        

        float[][] heightmap =  TerrainInterpolator.getBicubicInterpolatedChunk(
                macroValues,
                randomizer,
                clientWorldData.getDynamicInterpolationRatio(),
                clientWorldData.getRandomDampener()
        );
        
        cacheMap.put(getKey(x,y),heightmap);
        while(cacheList.size() > cacheSize){
            String currentChunk = cacheList.remove(0);
            cacheMap.remove(currentChunk);
        }
    }
    
    public void addFloatsToCache(int x, int y, float[][] values){
        cacheMap.put(getKey(x,y),values);
        while(cacheList.size() > cacheSize){
            String currentChunk = cacheList.remove(0);
            cacheMap.remove(currentChunk);
        }
    }
    
    
    
    public String getKey(int x, int y){
        return x + "-" + y;
    }
    
    
    public boolean containsHeightmapAtChunkPoint(int x, int y){
        return cacheMap.containsKey(getKey(x,y));
    }
    
    
    
    
    
    //ALL RETRIEVE
    public float[][] getHeightmapAtChunkPoint(int x, int y){
        return cacheMap.get(getKey(x,y));
    }
}
