'use strict';

const RATE_LIMIT_ENDPOINTS_GROUPS = {
    ANONYMOUS: 'anonymous',
    STATIC: 'static',
    STATIC_NAMED: 'static_named',
    DATAVIEW: 'dataview',
    DATAVIEW_SEARCH: 'dataview_search',
    ANALYSIS: 'analysis',
    ANALYSIS_CATALOG: 'analysis_catalog',
    TILE: 'tile',
    ATTRIBUTES: 'attributes',
    NAMED_LIST: 'named_list',
    NAMED_CREATE: 'named_create',
    NAMED_GET: 'named_get',
    NAMED: 'named',
    NAMED_UPDATE: 'named_update',
    NAMED_DELETE: 'named_delete',
    NAMED_TILES: 'named_tiles'
};

function rateLimit(userLimitsBackend, endpointGroup = null) {
    if (!isRateLimitEnabled(endpointGroup)) {
        return function rateLimitDisabledMiddleware(req, res, next) { next(); };
    }

    return function rateLimitMiddleware(req, res, next) {
        userLimitsBackend.getRateLimit(res.locals.user, endpointGroup, function (err, userRateLimit) {
            if (err) {
                return next(err);
            }

            if (!userRateLimit) {
                return next();
            }

            const [isBlocked, limit, remaining, retry, reset] = userRateLimit;

            res.set({
                'Carto-Rate-Limit-Limit': limit,
                'Carto-Rate-Limit-Remaining': remaining,
                'Carto-Rate-Limit-Reset': reset
            });

            if (isBlocked) {
                // retry is floor rounded in seconds by redis-cell
                res.set('Retry-After', retry + 1);

                let rateLimitError = new Error(
                    'You are over platform\'s limits: too many requests.' +
                    ' Please contact us to know more details'
                );
                rateLimitError.http_status = 429;
                rateLimitError.type = 'limit';
                rateLimitError.subtype = 'rate-limit';
                return next(rateLimitError);
            }

            return next();
        });
    };
}


function isRateLimitEnabled(endpointGroup) {
    return global.environment.enabledFeatures.rateLimitsEnabled &&
        endpointGroup &&
        global.environment.enabledFeatures.rateLimitsByEndpoint[endpointGroup];
}

module.exports = rateLimit;
module.exports.RATE_LIMIT_ENDPOINTS_GROUPS = RATE_LIMIT_ENDPOINTS_GROUPS;
