// Path: src/main/java/se/gustavkarlsson/rocketchat/jira_trigger/configuration/AppConfiguration.java
// @Singleton
// public class AppConfiguration {
// 	private static final String KEY_PREFIX = "app.";
// 	static final String IP_ADDRESS_KEY = KEY_PREFIX + "ip_address";
// 	static final String PORT_KEY = KEY_PREFIX + "port";
// 	static final String MAX_THREADS_KEY = KEY_PREFIX + "max_threads";
// 
// 	private final String ipAddress;
// 	private final int port;
// 	private final int maxThreads;
// 
// 	@Inject
// 	AppConfiguration(ConfigMap configMap) throws ValidationException {
// 		notNull(configMap);
// 		try {
// 			ipAddress = notBlank(configMap.getString(IP_ADDRESS_KEY), String.format("Non-blank %s must be provided", IP_ADDRESS_KEY));
// 			port = notNull(configMap.getLong(PORT_KEY), String.format("%s must be provided", PORT_KEY)).intValue();
// 			inclusiveBetween(1, Server.MAX_PORT_NUMBER, port, String.format("%s must be within %d and %d. Was: %d", PORT_KEY, 1, Server.MAX_PORT_NUMBER, port));
// 			maxThreads = notNull(configMap.getLong(MAX_THREADS_KEY), String.format("%s must be provided", MAX_THREADS_KEY)).intValue();
// 			inclusiveBetween(1, Integer.MAX_VALUE, maxThreads, String.format("%s must be within %d and %d. Was: %d", MAX_THREADS_KEY, 1, Integer.MAX_VALUE, maxThreads));
// 		} catch (Exception e) {
// 			throw new ValidationException(e);
// 		}
// 	}
// 
// 	public String getIpAddress() {
// 		return ipAddress;
// 	}
// 
// 	public int getPort() {
// 		return port;
// 	}
// 
// 	public int getMaxThreads() {
// 		return maxThreads;
// 	}
// }
// 
// Path: src/main/java/se/gustavkarlsson/rocketchat/jira_trigger/routes/DetectIssueRoute.java
// @Singleton
// public class DetectIssueRoute extends RocketChatMessageRoute {
// 	private static final Logger log = getLogger(DetectIssueRoute.class);
// 
// 	private final List<Validator> validators;
// 	private final JiraKeyParser jiraKeyParser;
// 	private final IssueRestClient issueClient;
// 	private final ToRocketChatMessageFactory messageFactory;
// 	private final AttachmentCreator attachmentCreator;
// 
// 	@Inject
// 	DetectIssueRoute(List<Validator> validators, JiraKeyParser jiraKeyParser, IssueRestClient issueClient,
// 					 ToRocketChatMessageFactory messageFactory, AttachmentCreator attachmentCreator) {
// 		this.validators = noNullElements(validators);
// 		this.jiraKeyParser = notNull(jiraKeyParser);
// 		this.issueClient = notNull(issueClient);
// 		this.messageFactory = notNull(messageFactory);
// 		this.attachmentCreator = notNull(attachmentCreator);
// 	}
// 
// 	@Override
// 	protected ToRocketChatMessage handle(Request request, Response response, FromRocketChatMessage fromRocketChatMessage) {
// 		log.debug("Validating message");
// 		if (!isValid(fromRocketChatMessage)) {
// 			log.info("Validation failed. Ignoring");
// 			return null;
// 		}
// 
// 		log.debug("Parsing keys from text: '{}'", fromRocketChatMessage.getText());
// 		Set<String> jiraKeys = jiraKeyParser.parse(fromRocketChatMessage.getText());
// 		if (jiraKeys.isEmpty()) {
// 			log.info("No keys found. Ignoring");
// 			return null;
// 		}
// 		log.info("Identified {} keys", jiraKeys.size());
// 		log.debug("Keys: {}", jiraKeys);
// 
// 		log.debug("Fetching issues...");
// 		Set<Issue> issues = getIssues(jiraKeys);
// 		log.info("Found {} issues", issues.size());
// 		if (issues.isEmpty()) {
// 			log.info("No issues found. Ignoring");
// 			return null;
// 		}
// 		log.debug("Issues: {}", issues.stream().map(Issue::getId).collect(toList()));
// 		log.debug("Creating message");
// 		ToRocketChatMessage message = messageFactory.create();
// 		message.setText(issues.size() == 1 ? "Found 1 issue" : String.format("Found %d issues", issues.size()));
// 		List<ToRocketChatAttachment> attachments = createAttachments(issues);
// 		message.setAttachments(attachments);
// 		return message;
// 	}
// 
// 	private boolean isValid(FromRocketChatMessage fromRocketChatMessage) {
// 		return validators.stream().allMatch(validator -> validator.isValid(fromRocketChatMessage));
// 	}
// 
// 	private Set<Issue> getIssues(Set<String> jiraKeys) {
// 		return jiraKeys.parallelStream()
// 				.map(this::getIssue)
// 				.filter(Objects::nonNull)
// 				.collect(Collectors.toSet());
// 	}
// 
// 	private Issue getIssue(String jiraKey) {
// 		try {
// 			return issueClient.getIssue(jiraKey).claim();
// 		} catch (RestClientException e) {
// 			if (e.getStatusCode().or(0) != NOT_FOUND_404) {
// 				log.error("Jira client error", e);
// 			}
// 			return null;
// 		}
// 	}
// 
// 	private List<ToRocketChatAttachment> createAttachments(Set<Issue> issues) {
// 		return issues.stream()
// 				.map(attachmentCreator::create)
// 				.collect(toList());
// 	}
// }


import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import se.gustavkarlsson.rocketchat.jira_trigger.configuration.AppConfiguration;
import se.gustavkarlsson.rocketchat.jira_trigger.routes.DetectIssueRoute;
package se.gustavkarlsson.rocketchat.jira_trigger.server;


public class ServerModule extends AbstractModule {
	@Override
	protected void configure() {
	}

	@Provides
	@Singleton
// Path: src/main/java/se/gustavkarlsson/rocketchat/jira_trigger/configuration/AppConfiguration.java
// @Singleton
// public class AppConfiguration {
// 	private static final String KEY_PREFIX = "app.";
// 	static final String IP_ADDRESS_KEY = KEY_PREFIX + "ip_address";
// 	static final String PORT_KEY = KEY_PREFIX + "port";
// 	static final String MAX_THREADS_KEY = KEY_PREFIX + "max_threads";
// 
// 	private final String ipAddress;
// 	private final int port;
// 	private final int maxThreads;
// 
// 	@Inject
// 	AppConfiguration(ConfigMap configMap) throws ValidationException {
// 		notNull(configMap);
// 		try {
// 			ipAddress = notBlank(configMap.getString(IP_ADDRESS_KEY), String.format("Non-blank %s must be provided", IP_ADDRESS_KEY));
// 			port = notNull(configMap.getLong(PORT_KEY), String.format("%s must be provided", PORT_KEY)).intValue();
// 			inclusiveBetween(1, Server.MAX_PORT_NUMBER, port, String.format("%s must be within %d and %d. Was: %d", PORT_KEY, 1, Server.MAX_PORT_NUMBER, port));
// 			maxThreads = notNull(configMap.getLong(MAX_THREADS_KEY), String.format("%s must be provided", MAX_THREADS_KEY)).intValue();
// 			inclusiveBetween(1, Integer.MAX_VALUE, maxThreads, String.format("%s must be within %d and %d. Was: %d", MAX_THREADS_KEY, 1, Integer.MAX_VALUE, maxThreads));
// 		} catch (Exception e) {
// 			throw new ValidationException(e);
// 		}
// 	}
// 
// 	public String getIpAddress() {
// 		return ipAddress;
// 	}
// 
// 	public int getPort() {
// 		return port;
// 	}
// 
// 	public int getMaxThreads() {
// 		return maxThreads;
// 	}
// }
// 
// Path: src/main/java/se/gustavkarlsson/rocketchat/jira_trigger/routes/DetectIssueRoute.java
// @Singleton
// public class DetectIssueRoute extends RocketChatMessageRoute {
// 	private static final Logger log = getLogger(DetectIssueRoute.class);
// 
// 	private final List<Validator> validators;
// 	private final JiraKeyParser jiraKeyParser;
// 	private final IssueRestClient issueClient;
// 	private final ToRocketChatMessageFactory messageFactory;
// 	private final AttachmentCreator attachmentCreator;
// 
// 	@Inject
// 	DetectIssueRoute(List<Validator> validators, JiraKeyParser jiraKeyParser, IssueRestClient issueClient,
// 					 ToRocketChatMessageFactory messageFactory, AttachmentCreator attachmentCreator) {
// 		this.validators = noNullElements(validators);
// 		this.jiraKeyParser = notNull(jiraKeyParser);
// 		this.issueClient = notNull(issueClient);
// 		this.messageFactory = notNull(messageFactory);
// 		this.attachmentCreator = notNull(attachmentCreator);
// 	}
// 
// 	@Override
// 	protected ToRocketChatMessage handle(Request request, Response response, FromRocketChatMessage fromRocketChatMessage) {
// 		log.debug("Validating message");
// 		if (!isValid(fromRocketChatMessage)) {
// 			log.info("Validation failed. Ignoring");
// 			return null;
// 		}
// 
// 		log.debug("Parsing keys from text: '{}'", fromRocketChatMessage.getText());
// 		Set<String> jiraKeys = jiraKeyParser.parse(fromRocketChatMessage.getText());
// 		if (jiraKeys.isEmpty()) {
// 			log.info("No keys found. Ignoring");
// 			return null;
// 		}
// 		log.info("Identified {} keys", jiraKeys.size());
// 		log.debug("Keys: {}", jiraKeys);
// 
// 		log.debug("Fetching issues...");
// 		Set<Issue> issues = getIssues(jiraKeys);
// 		log.info("Found {} issues", issues.size());
// 		if (issues.isEmpty()) {
// 			log.info("No issues found. Ignoring");
// 			return null;
// 		}
// 		log.debug("Issues: {}", issues.stream().map(Issue::getId).collect(toList()));
// 		log.debug("Creating message");
// 		ToRocketChatMessage message = messageFactory.create();
// 		message.setText(issues.size() == 1 ? "Found 1 issue" : String.format("Found %d issues", issues.size()));
// 		List<ToRocketChatAttachment> attachments = createAttachments(issues);
// 		message.setAttachments(attachments);
// 		return message;
// 	}
// 
// 	private boolean isValid(FromRocketChatMessage fromRocketChatMessage) {
// 		return validators.stream().allMatch(validator -> validator.isValid(fromRocketChatMessage));
// 	}
// 
// 	private Set<Issue> getIssues(Set<String> jiraKeys) {
// 		return jiraKeys.parallelStream()
// 				.map(this::getIssue)
// 				.filter(Objects::nonNull)
// 				.collect(Collectors.toSet());
// 	}
// 
// 	private Issue getIssue(String jiraKey) {
// 		try {
// 			return issueClient.getIssue(jiraKey).claim();
// 		} catch (RestClientException e) {
// 			if (e.getStatusCode().or(0) != NOT_FOUND_404) {
// 				log.error("Jira client error", e);
// 			}
// 			return null;
// 		}
// 	}
// 
// 	private List<ToRocketChatAttachment> createAttachments(Set<Issue> issues) {
// 		return issues.stream()
// 				.map(attachmentCreator::create)
// 				.collect(toList());
// 	}
// }


// Path: src/main/java/se/gustavkarlsson/rocketchat/jira_trigger/server/ServerModule.java
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import se.gustavkarlsson.rocketchat.jira_trigger.configuration.AppConfiguration;
import se.gustavkarlsson.rocketchat.jira_trigger.routes.DetectIssueRoute;

package se.gustavkarlsson.rocketchat.jira_trigger.server;


public class ServerModule extends AbstractModule {
	@Override
	protected void configure() {
	}

	@Provides
	@Singleton
	Server provideServer(AppConfiguration appConfig, DetectIssueRoute detectIssueRoute, JiraServerInfoLogger jiraServerInfoLogger) {