const { Injectable } = require('flitter-di')
const ImplementationError = require('libflitter/errors/ImplementationError')
const ServiceConfig = require('./ServiceConfig')

class ServiceManager extends Injectable {
    static SERVICE_STATE_STOPPED = 'stopped'
    static SERVICE_STATE_ERROR = 'error'
    static SERVICE_STATE_RUNNING = 'running'

    _command_restart_service = '%%SERVICE%%'
    _command_start_service = '%%SERVICE%%'
    _command_stop_service = '%%SERVICE%%'
    _command_reload_service = '%%SERVICE%%'
    _command_enable_service = '%%SERVICE%%'
    _command_disable_service = '%%SERVICE%%'
    _command_daemon_reload = ''

    _group_services_by = ' '

    constructor(host) {
        super()
        this._host = host
    }

    async status(...services) {
        throw new ImplementationError()
    }

    async install(config) {
        throw new ImplementationError()
    }

    new_config() {
        return new ServiceConfig()
    }

    async start(...services) {
        await this._standard_format_execution(services, this._command_start_service)
    }

    async stop(...services) {
        await this._standard_format_execution(services, this._command_stop_service)
    }

    async restart(...services) {
        await this._standard_format_execution(services, this._command_restart_service)
    }

    async reload(...services) {
        await this._standard_format_execution(services, this._command_reload_service)
    }

    async enable(...services) {
        await this._standard_format_execution(services, this._command_enable_service)
    }

    async disable(...services) {
        await this._standard_format_execution(services, this._command_disable_service)
    }

    async daemon_reload() {
        await this._host.run_line_result(this._command_daemon_reload)
    }

    async _standard_format_execution(items, command, replace = '%%SERVICE%%') {
        if ( this._group_services_by ) {
            items = [items.join(this._group_services_by)]
        }

        for ( const item of items ) {
            const result = await this._host.execute(command.replace(replace, item))
            if ( result.exit_code !== 0 ) {
                throw new Error('Error encountered while executing command: '+result.stderr.join('\n'))
            }
        }
    }
}

module.exports = exports = ServiceManager