package com.priusis.client.service;

import com.priusis.client.extensions.ExtensionService;
import com.priusis.client.extensions.http.HttpService;
import com.priusis.client.service.conf.PcCoreConfiguration;
import com.priusis.client.service.conf.PcExtensionConfiguration;
import com.priusis.client.service.core.MqttService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * Created by priusis on 29.09.17.
 */
@Slf4j
public abstract class DefaultTenantManagerService implements TenantManagerService {

    @Autowired
    private PcCoreConfiguration configuration;

    private Map<String, TenantServiceRegistry> gateways;
    private HttpService httpService;

    public abstract MqttService getGatewayService(PcCoreConfiguration configuration, Consumer<String> extensionsConfigListener);

    @PostConstruct
    public void init() {
        gateways = new HashMap<>();
        String label = configuration.getLabel();
        log.info("[{}] Initializing client", configuration.getLabel());
        MqttService service = null;
        try {
            TenantServiceRegistry tenantServiceRegistry = new TenantServiceRegistry();
            service = getGatewayService(configuration, c -> {
            });
            tenantServiceRegistry.setService(service);
            for (PcExtensionConfiguration extensionConfiguration : configuration.getExtensions()) {
                log.info("[{}] Initializing extension: [{}]", configuration.getLabel(), extensionConfiguration.getType());
                ExtensionService extension = tenantServiceRegistry.createExtensionServiceByType(service, extensionConfiguration.getType());
                extension.init(extensionConfiguration);
                if (extensionConfiguration.getType().equals("HTTP")) {
                    httpService = (HttpService) extension;
                }
            }
            gateways.put(label, (TenantServiceRegistry) tenantServiceRegistry);
        } catch (Exception e) {
            log.info("[{}] Failed to initialize the service ", label, e);
            try {
                if (service != null) {
                    service.destroy();
                }
            } catch (Exception exc) {
                log.info("[{}] Failed to stop the service ", label, exc);
            }
        }
    }

    @Override
    public void processRequest(String token, String body) throws Exception {
        httpService.processRequest(token, body);
    }

    @Override
    public File flushRpcDataToFile(MqttRpcDataMessage mqttRpcDataMessage) throws IOException {
        return httpService.flushRpcDataToFile(mqttRpcDataMessage);
    }

    @Override
    public MqttRpcDataMessage readFromFile(String method) throws IOException {
        return httpService.readFromFile(method);
    }

    @PreDestroy
    public void stop() {
        for (String label : gateways.keySet()) {
            try {
                TenantServiceRegistry registry = gateways.get(label);
                for (ExtensionService extension : registry.getExtensions().values()) {
                    try {
                        extension.destroy();
                    } catch (Exception e) {
                        log.info("[{}] Failed to stop the extension ", label, e);
                    }
                }
                registry.getService().destroy();
            } catch (Exception e) {
                log.info("[{}] Failed to stop the service ", label, e);
            }
        }
    }
}
