"use strict";

const fs      = require('fs');
const console = require('gifer-console');

function PluginRegistry(filePath){
    var state = { plugins: {} };

    try {
        state = JSON.parse(fs.readFileSync(filePath, 'utf8'));
        console.log('[plugins] registry loaded: ' + Object.keys(state.plugins || {}).length + ' plugin(s)', console.logLevel.DEBUG);
    } catch (e) {
        if (e.code !== 'ENOENT'){
            console.warn('[plugins] registry parse failed: ' + e.message, console.logLevel.WARN);
            throw new Error('invalid plugin registry: ' + e.message);
        }
    }

    function save(next){
        var tmp = filePath + '.tmp';

        fs.writeFileSync(tmp, JSON.stringify(next, null, 2), 'utf8');
        try {
            fs.renameSync(tmp, filePath);
            state = next;
        } catch (e) {
            try { fs.unlinkSync(tmp); } catch (ignore) {}
            throw e;
        }
    }

    function mutate(fn){
        var next = JSON.parse(JSON.stringify(state));

        fn(next.plugins);
        save(next);
    }

    this.get  = function(id){ return state.plugins[id] || null; };
    this.list = function(){
        return Object.keys(state.plugins).map(function(id){
            return Object.assign({ id: id }, state.plugins[id]);
        });
    };
    this.upsert = function(id, patch){
        mutate(function(plugins){
            plugins[id] = Object.assign({ enabled: false, keepAlive: false }, plugins[id], patch);
        });
    };
    this.setEnabled = function(id, enabled){
        mutate(function(plugins){ plugins[id].enabled = !!enabled; });
    };
    this.setKeepAlive = function(id, keepAlive){
        mutate(function(plugins){ plugins[id].keepAlive = !!keepAlive; });
    };
    this.remove = function(id){ mutate(function(plugins){ delete plugins[id]; }); };
}

module.exports = PluginRegistry;
