'use strict';

const NamedMapMapConfigProvider = require('../models/mapconfig/provider/named-map-provider');
const templateName = require('../backends/template_maps').templateName;

const LruCache = require("lru-cache");

const TEN_MINUTES_IN_MILLISECONDS = 1000 * 60 * 10;
const ACTIONS = ['update', 'delete'];

function NamedMapProviderCache(
    templateMaps,
    pgConnection,
    metadataBackend,
    userLimitsBackend,
    mapConfigAdapter,
    affectedTablesCache
) {
    this.templateMaps = templateMaps;
    this.pgConnection = pgConnection;
    this.metadataBackend = metadataBackend;
    this.userLimitsBackend = userLimitsBackend;
    this.mapConfigAdapter = mapConfigAdapter;
    this.affectedTablesCache = affectedTablesCache;

    this.providerCache = new LruCache({ max: 2000, maxAge: TEN_MINUTES_IN_MILLISECONDS });

    ACTIONS.forEach(action => templateMaps.on(action, (...args) => this.invalidate(...args)));
}

module.exports = NamedMapProviderCache;

NamedMapProviderCache.prototype.get = function(user, templateId, config, authToken, params, callback) {
    const namedMapKey = createNamedMapKey(user, templateId);
    const namedMapProviders = this.providerCache.get(namedMapKey) || {};
    const providerKey = createProviderKey(config, authToken, params);

    if (namedMapProviders.hasOwnProperty(providerKey)) {
        return callback(null, namedMapProviders[providerKey]);
    }

    namedMapProviders[providerKey] = new NamedMapMapConfigProvider(
        this.templateMaps,
        this.pgConnection,
        this.metadataBackend,
        this.userLimitsBackend,
        this.mapConfigAdapter,
        this.affectedTablesCache,
        user,
        templateId,
        config,
        authToken,
        params
    );

    this.providerCache.set(namedMapKey, namedMapProviders);

    return callback(null, namedMapProviders[providerKey]);
};

NamedMapProviderCache.prototype.invalidate = function(user, templateId) {
    this.providerCache.del(createNamedMapKey(user, templateId));
};

function createNamedMapKey(user, templateId) {
    return user + ':' + templateName(templateId);
}

const providerKeyTpl = ctx => `${ctx.authToken}:${ctx.configHash}:${ctx.format}:${ctx.layer}:${ctx.scale_factor}`;

function createProviderKey(config, authToken, params) {
    const defaults = {
        authToken: authToken || '',
        configHash: NamedMapMapConfigProvider.configHash(config),
        layer: '',
        format: '',
        scale_factor: 1
    };
    const ctx = Object.assign({}, defaults, params);

    return providerKeyTpl(ctx);
}

@@ -8,16 +8,56 @@
 rict';%0A%0A
+const LruCache = require(%22lru-cache%22);%0A%0A
 const Na
@@ -147,16 +147,18 @@
 );%0Aconst
+ %7B
  templat
@@ -162,16 +162,18 @@
 lateName
+ %7D
  = requi
@@ -207,61 +207,8 @@
 ps')
-.templateName;%0A%0Aconst LruCache = require(%22lru-cache%22)
 ;%0A%0Ac
@@ -2019,32 +2019,33 @@
 reateNamedMapKey
+ 
 (user, templateI
@@ -2064,21 +2064,19 @@
 urn 
+%60$%7B
 user
- + ':' + 
+%7D:$%7B
 temp
@@ -2095,16 +2095,18 @@
 plateId)
+%7D%60
 ;%0A%7D%0A%0Acon
@@ -2236,32 +2236,33 @@
 reateProviderKey
+ 
 (config, authTok

Use template string