'use strict';

const Projection = require('./projection.js');
const TTLList = require('./ttl-list.js');

module.exports = class UnleashClientMetrics {
    constructor (clientMetricsStore) {
        this.globalCount = 0;
        this.apps = {};

        this.lastHourProjection = new Projection();
        this.lastMinuteProjection = new Projection();

        this.lastHourList = new TTLList({
            interval: 10000,
        });

        this.lastMinuteList = new TTLList({
            interval: 10000,
            expireType: 'minutes',
            expireAmount: 1,
        });

        this.lastHourList.on('expire', (toggles) => {
            Object.keys(toggles).forEach(toggleName => {
                this.lastHourProjection.substract(toggleName, toggles[toggleName]);
            });
        });
        this.lastMinuteList.on('expire', (toggles) => {
            Object.keys(toggles).forEach(toggleName => {
                this.lastMinuteProjection.substract(toggleName, toggles[toggleName]);
            });
        });
        clientMetricsStore.on('metrics', (m) => this.addPayload(m));
    }

    getAppsWithToggles () {
        const apps = [];
        Object.keys(this.apps).forEach(appName => {
            const seenToggles = Object.keys(this.apps[appName].seenToggles);
            const metricsCount = this.apps[appName].count;
            apps.push({ appName, seenToggles, metricsCount });
        });
        return apps;
    }
    getSeenTogglesByAppName (appName) {
        return this.apps[appName] ? Object.keys(this.apps[appName].seenToggles) : [];
    }

    getSeenAppsPerToggle () {
        const toggles = {};
        Object.keys(this.apps).forEach(appName => {
            Object.keys(this.apps[appName].seenToggles).forEach((seenToggleName) => {
                if (!toggles[seenToggleName]) {
                    toggles[seenToggleName] = [];
                }
                toggles[seenToggleName].push({ appName });
            });
        });
        return toggles;
    }

    getTogglesMetrics () {
        return {
            lastHour: this.lastHourProjection.getProjection(),
            lastMinute: this.lastMinuteProjection.getProjection(),
        };
    }

    addPayload (data) {
        const { appName, bucket } = data;
        const app = this.getApp(appName);
        this.addBucket(app, bucket);
    }

    getApp (appName) {
        this.apps[appName] = this.apps[appName] || { seenToggles: {}, count: 0 };
        return this.apps[appName];
    }

    addBucket (app, bucket) {
        let count = 0;
        // TODO stop should be createdAt
        const { stop, toggles } = bucket;

        const toggleNames = Object.keys(toggles);

        toggleNames.forEach((n) => {
            const entry = toggles[n];
            this.lastHourProjection.add(n, entry);
            this.lastMinuteProjection.add(n, entry);
            count += (entry.yes + entry.no);
        });

        this.lastHourList.add(toggles, stop);
        this.lastMinuteList.add(toggles, stop);

        this.globalCount += count;
        app.count += count;
        this.addSeenToggles(app, toggleNames);
    }

    addSeenToggles (app, toggleNames) {
        toggleNames.forEach(t => {
            app.seenToggles[t] = true;
        });
    }

    destroy () {
        this.lastHourList.destroy();
        this.lastMinuteList.destroy();
    }
};