package com.bsmlab.dfx.agent.config;

import com.bsmlab.dfx.agent.config.jmx.DfxJmxRegistrar;
import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
@Getter
public class AgentConfigReader {
    private AgentConfigDto agentConfigDto = null;
    private Map<String, String> knownAgentStatusMap;
    @Value("${spring.application.name}")
    private String applicationName;
    @Value("${spring.application.version}")
    private String applicationVersion;
    @Value("${spring.application.commitId}")
    private String applicationCommitId;
    @Setter
    private boolean connectedConsole;
    private final ConfigurableApplicationContext configurableApplicationContext;

    public AgentConfigReader(ConfigurableApplicationContext configurableApplicationContext) {
        this.configurableApplicationContext = configurableApplicationContext;
    }

    public void loadConfigFile(String configFilePath) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            this.agentConfigDto = objectMapper.readValue(new File(configFilePath), AgentConfigDto.class);
            this.knownAgentStatusMap = new HashMap<>();
            List<AgentConfigDto.KnownAgent> knownAgentList = this.agentConfigDto.getKnownAgentList();
            if(knownAgentList != null) {
                for(AgentConfigDto.KnownAgent knownAgent : knownAgentList) {
                    this.knownAgentStatusMap.put(knownAgent.getHostId(), "DOWN");
                }
            }
            DfxJmxRegistrar.register(this.agentConfigDto.getMyHostId(), this.configurableApplicationContext);
        } catch (DatabindException e) {
            log.error("cannot parse a setting file. {}", configFilePath, e);
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error("cannot read a setting file. {}", configFilePath);
            log.error(e.getMessage(), e);
        }
    }

    public synchronized String getKnownAgentStatus(String knownAgentHostId) {
        return this.knownAgentStatusMap.get(knownAgentHostId);
    }

    public synchronized void setKnownAgentStatus(String knownAgentHostId, String knownAgentStatus) {
        this.knownAgentStatusMap.put(knownAgentHostId, knownAgentStatus);
    }

    public AgentConfigDto.DropBox getDropBox(String dropBoxId) {
        AgentConfigDto.DropBox found = null;
        for(AgentConfigDto.DropBox dropBox : this.agentConfigDto.getDropBoxConfig().getDropBoxList()) {
            if(dropBox.getDropBoxId().equals(dropBoxId)) {
                found = dropBox;
                break;
            }
        }
        return found;
    }

    public AgentConfigDto.KnownAgent getKnownAgent(String hostId) {
        AgentConfigDto.KnownAgent found = null;
        for(AgentConfigDto.KnownAgent knownAgent : this.agentConfigDto.getKnownAgentList()) {
            if(knownAgent.getHostId().equals(hostId)) {
                found = knownAgent;
                break;
            }
        }
        return found;
    }

    public List<AgentConfigDto.Postman> getScheduledTypePostmanList() {
        List<AgentConfigDto.Postman> postmanList = null;
        for(AgentConfigDto.Postman postman : this.agentConfigDto.getPostmanConfig().getPostmanList()) {
            if(AgentConfigDto.ActionType.SCHEDULED == postman.getAction().getType()) {
                if(postmanList == null) {
                    postmanList = new ArrayList<>();
                }
                postmanList.add(postman);
            }
        }
        return postmanList;
    }
}
