package eu.dnetlib.lbs;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

import io.prometheus.client.exporter.MetricsServlet;
import io.prometheus.client.hotspot.DefaultExports;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import eu.dnetlib.lbs.elasticsearch.Event;
import eu.dnetlib.lbs.elasticsearch.Notification;
import eu.dnetlib.lbs.properties.ElasticSearchProperties;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Tag;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
@EnableScheduling
@EnableTransactionManagement
@EnableElasticsearchRepositories(basePackageClasses = { Event.class, Notification.class })
public class LiteratureBrokerServiceConfiguration {

	private static final Log log = LogFactory.getLog(LiteratureBrokerServiceConfiguration.class);

	@Autowired
	private ElasticSearchProperties elasticSearchProperties;

	public static final String TAG_EVENTS = "Events";
	public static final String TAG_SUBSCRIPTIONS = "Subscriptions";
	public static final String TAG_NOTIFICATIONS = "Notifications";
	public static final String TAG_TOPIC_TYPES = "Topic Types";
	public static final String TAG_OPENAIRE = "OpenAIRE";

	@Bean
	public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
		final String[] arr = this.elasticSearchProperties.getClusterNodes().split(":");
		final String server = arr[0];
		final Integer port = Integer.parseInt(arr[1]);

		final Settings settings = Settings
				.builder()
				.put("cluster.name", this.elasticSearchProperties.getClusterName())
				.build();

		final TransportClient client = new PreBuiltTransportClient(settings, new ArrayList<>());
		client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(server), port));

		return new ElasticsearchTemplate(client);

	}

	@Bean
	public static Docket newSwaggerDocket() {
		log.info("Initializing SWAGGER...");

		return new Docket(DocumentationType.SWAGGER_2)
				.select()
				.apis(RequestHandlerSelectors.any())
				.paths(p -> p.startsWith("/api/"))
				.build()
				.tags(
						new Tag(TAG_EVENTS, "Events management"),
						new Tag(TAG_SUBSCRIPTIONS, "Subscriptions management"),
						new Tag(TAG_NOTIFICATIONS, "Notifications management"),
						new Tag(TAG_TOPIC_TYPES, "Topic types management"),
						new Tag(TAG_OPENAIRE, "OpenAIRE use case"))
				.apiInfo(new ApiInfo(
						"Literature Broker Service",
						"APIs documentation",
						"1.1",
						"urn:tos",
						ApiInfo.DEFAULT_CONTACT,
						"Apache 2.0",
						"http://www.apache.org/licenses/LICENSE-2.0"));

	}

	@Bean
	@ConditionalOnMissingBean(name = "prometheusMetricsServletRegistrationBean")
	ServletRegistrationBean prometheusMetricsServletRegistrationBean(@Value("${prometheus.metrics.path:/metrics}") final String metricsPath) {
		DefaultExports.initialize();
		return new ServletRegistrationBean(new MetricsServlet(), metricsPath);
	}

}
