package eu.eudat.configurations.dynamicfunder;

import eu.eudat.configurations.dynamicfunder.entities.Configuration;
import eu.eudat.configurations.dynamicfunder.entities.Property;
import eu.eudat.models.data.dynamicfields.Dependency;
import eu.eudat.models.data.dynamicfields.DynamicField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;

@Service("dynamicFunderConfiguration")
@Profile({ "production", "staging", "docker" })
public class DynamicFunderConfigurationProdImpl implements DynamicFunderConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(DynamicFunderConfigurationProdImpl.class);

	private Configuration configuration;
	private List<DynamicField> fields;
	private Environment environment;

	public DynamicFunderConfigurationProdImpl(Environment environment) {
		this.environment = environment;
	}

	@Override
	public Configuration getConfiguration() {
		if (this.configuration != null) return this.configuration;
		String fileUrl = this.environment.getProperty("configuration.dynamicFunderUrl");
		logger.info("Loaded also config file: " + fileUrl);
		String current = null;
		InputStream is = null;
		try {
			current = new java.io.File(".").getCanonicalPath();

			JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class);
			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream();
			this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is);
		} catch (Exception ex) {
			logger.error("Cannot find in folder" + current, ex);
		} finally {
			try {
				if (is != null) is.close();
			} catch (IOException e) {
				logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e);
			}
		}
		return this.configuration;
	}

	@Override
	public List<DynamicField> getFields() {
		if (this.fields != null) return this.fields;
		Configuration configuration = this.getConfiguration();
		List<DynamicField> fields = new LinkedList<>();
		List<Property> properties = configuration.getConfigurationProperties();
		properties.stream().forEach(item -> {
			DynamicField dynamicField = new DynamicField();
			dynamicField.setId(item.getId());
			dynamicField.setName(item.getName());
			dynamicField.setQueryProperty(item.getQueryProperty());
			dynamicField.setRequired(item.getRequired());
			List<Dependency> dependencies = new LinkedList<>();
			item.getDependencies().stream().forEach(dependency -> {
				Dependency modelDependency = new Dependency();
				modelDependency.setId(dependency.getId());
				modelDependency.setQueryProperty(dependency.getQueryProperty());
				dependencies.add(modelDependency);
			});
			dynamicField.setDependencies(dependencies);
			fields.add(dynamicField);
		});
		this.fields = fields;
		return fields;
	}
}
