"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resetRequests = resetRequests;
exports.createRequest = createRequest;
exports.updateRequest = updateRequest;
exports.queryRequest = queryRequest;
exports.findRequest = findRequest;
exports.filterRequests = filterRequests;
const uuid_1 = require("uuid");
const debug_1 = require("./debug");
const debug = (0, debug_1.createDebug)('signalk-server:requestResponse');
const requests = {};
const pruneRequestTimeout = 60 * 60 * 1000;
const pruneIntervalRate = 15 * 60 * 1000;
let pruneInterval;
function resetRequests() {
    Object.keys(requests).forEach((id) => {
        delete requests[id];
    });
}
function createRequest(app, type, clientRequest, user, clientIp, updateCb) {
    return new Promise((resolve) => {
        const requestId = clientRequest.requestId
            ? clientRequest.requestId
            : (0, uuid_1.v4)();
        const request = {
            requestId: requestId,
            type: type,
            clientRequest: clientRequest,
            ip: clientIp,
            date: new Date(),
            state: 'PENDING',
            statusCode: 202,
            updateCb: updateCb,
            user: user
        };
        requests[request.requestId] = request;
        debug('createRequest %j', request);
        if (!pruneInterval) {
            pruneInterval = setInterval(pruneRequests, pruneIntervalRate);
            app.intervals.push(pruneInterval);
        }
        resolve(request);
    });
}
function createReply(request) {
    const reply = {
        state: request.state,
        requestId: request.requestId,
        statusCode: request.statusCode,
        message: request.message,
        href: `/signalk/v1/requests/${request.requestId}`,
        ip: request.ip,
        user: request.user
    };
    if (request.type === 'put') {
        reply.put = request.data;
    }
    else if (request.type === 'delete') {
        reply.delete = request.data;
    }
    else if (request.type === 'accessRequest') {
        reply.accessRequest = request.data;
    }
    debug('createReply %j', reply);
    return reply;
}
function updateRequest(requestId, state, { statusCode = null, data = null, message = null, percentComplete = null }) {
    return new Promise((resolve, reject) => {
        const request = requests[requestId];
        if (!request) {
            reject(new Error('request not found'));
            return;
        }
        if (state) {
            request.state = state;
        }
        if (statusCode !== null) {
            request.statusCode = statusCode;
        }
        if (message) {
            request.message = message;
        }
        if (percentComplete !== null) {
            request.percentComplete = percentComplete;
        }
        if (data) {
            request.data = data;
        }
        const reply = createReply(request);
        if (request.updateCb) {
            request.updateCb(reply);
        }
        resolve(reply);
    });
}
function queryRequest(requestId) {
    return new Promise((resolve, reject) => {
        const request = requests[requestId];
        if (!requestId || !request) {
            reject(new Error('not found'));
            return;
        }
        resolve(createReply(request));
    });
}
function findRequest(matcher) {
    return Object.values(requests).find(matcher);
}
function filterRequests(type, state) {
    return Object.values(requests).filter((r) => r.type === type && (state === null || r.state === state));
}
function pruneRequests() {
    debug('pruning requests');
    Object.keys(requests).forEach((id) => {
        const request = requests[id];
        const diff = Date.now() - request.date.getTime();
        if (diff > pruneRequestTimeout) {
            delete requests[id];
            debug('pruned request %s', id);
        }
    });
}
//# sourceMappingURL=requestResponse.js.map