"use strict";

var child_process = require('child_process');
var fork = child_process.fork;
var exec = child_process.exec;

var MAXIMUM_NICENESS = 19;

var StringMap = require('stringmap');

var database = require('../../database');

// var ONE_HOUR = 60*60*1000;

/*
    territoireId => mutable{
        graph: aGraph
        lastAccessTime?: timestamp
        builtTime: timestamp
    }
*/
var cache = new Map();

var scheduledRefreshes = new Map/*<territoireId, Process>*/()

function refreshCacheEntry(territoireId){
    //console.log('refreshCacheEntry', territoireId);
    
    if(scheduledRefreshes.has(territoireId))
        return; // already scheduled
    
    var w = fork(require.resolve('./territoireGraphBuilder-worker'), [territoireId]);
    
    scheduledRefreshes.set(territoireId, w);
    
    w.on('message', function(graph){
        // it's the graph, 
        cache.set(territoireId, {
            graph: graph,
            buildTime: Date.now()
        });
        
        w.kill();
    });
    
    w.on('exit', function(){
        scheduledRefreshes.delete(territoireId);
    })
    
    exec( ['renice', '-n', MAXIMUM_NICENESS, w.pid].join(' ') );
}


module.exports = function(territoireId){
    var entry = cache.get(territoireId);
    
    console.log('territoireGraphCache entry', !!entry);
    
    if(entry){
        entry.lastAccessTime = Date.now();
        
        // schedule a refresh of the entry
        refreshCacheEntry(territoireId)
        
        return Promise.resolve({
            graph: entry.graph,
            complete: true 
        });
    }
    else{
        // schedule getting the full graph
        refreshCacheEntry(territoireId)

        // Get the territoire query results and make a graph out of that to be returned ASAP
        return database.complexQueries.getValidTerritoireQueryResultResources(territoireId)
            .then(function(resources){            
                var nodes = new StringMap();
            
                resources.forEach(function(res){
                    if(res.alias_of !== null)
                        return;

                    var idKey = String(res.id);

                    nodes.set(idKey, Object.assign({
                        depth: 0
                    }, res));
                });
            
                return {
                    nodes: nodes.values(),
                    edges: []
                };
            })
            .then(function(graph){
                return {
                    graph: graph,
                    complete: false 
                };
            })
    }
    
}

@@ -121,36 +121,8 @@
 c;%0A%0A
-var MAXIMUM_NICENESS = 19;%0A%0A
 var 
@@ -203,36 +203,109 @@
 );%0A%0A
-// var ONE_HOUR = 60*60*1000
+var MAXIMUM_NICENESS = 19;%0A%0Avar ONE_HOUR = 60*60*1000;%0A%0Avar CACHE_ENTRY_NO_ACCESS_MAX_TIME = ONE_HOUR
 ;%0A%0A/
@@ -450,24 +450,404 @@
 new Map();%0A%0A
+setTimeout(function cleanupCache()%7B%0A    setTimeout(cleanupCache, CACHE_ENTRY_NO_ACCESS_MAX_TIME/4);%0A    %0A    cache.forEach(function(entry, key)%7B%0A        if(Date.now() - entry.lastAccessTime %3C CACHE_ENTRY_NO_ACCESS_MAX_TIME)%7B%0A            // entry hasn't been accessed in a long time    %0A            cache.delete(key);%0A        %7D%0A    %7D);%0A    %0A%7D, CACHE_ENTRY_NO_ACCESS_MAX_TIME/4);%0A%0A%0A
 var schedule
@@ -1373,16 +1373,56 @@
 ildTime:
+ Date.now(),%0A            lastAccessTime:
  Date.no
@@ -2024,21 +2024,33 @@
     
-complete: tru
+buildTime: entry.buildTim
 e %0A 

Remove old territoire graph cache entries after an hour. Fixes #240.