package de.cronn.proxy.ssh;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.JSch;

import de.cronn.proxy.ssh.util.Utils;

public final class JSchHelper {

	private static final Logger log = LoggerFactory.getLogger(JSchHelper.class);

	private static final String SERVER_HOST_KEY_SEPARATOR = ",";

	private static final String JSCH_CONFIG_KEY_SERVER_HOST_KEY = "server_host_key";
	private static final String JSCH_CONFIG_KEY_PREFERRED_AUTHENTICATIONS = "PreferredAuthentications";

	private static class HostKeyComparator implements Comparator<HostKeyType> {

		private final List<HostKeyType> sortOrder;

		protected HostKeyComparator(List<HostKeyType> sortOrder) {
			this.sortOrder = sortOrder;
		}

		protected HostKeyComparator(HostKeyType... sortOrder) {
			this(Arrays.asList(sortOrder));
		}

		@Override
		public int compare(HostKeyType a, HostKeyType b) {
			int indexA = sortOrder.indexOf(a);
			int indexB = sortOrder.indexOf(b);
			return Integer.compare(indexA, indexB);
		}
	}

	private static final Comparator<HostKeyType> CMP_PREFER_ECDSA = new HostKeyComparator(
		HostKeyType.ECDSA256, HostKeyType.ECDSA384, HostKeyType.ECDSA521, HostKeyType.SSH_RSA, HostKeyType.SSH_DSS
	);

	private static final Comparator<HostKeyType> CMP_PREFER_RSA = new HostKeyComparator(
		HostKeyType.SSH_RSA, HostKeyType.ECDSA256, HostKeyType.ECDSA384, HostKeyType.ECDSA521, HostKeyType.SSH_DSS
	);

	public enum ServerHostKeySortOrder {
		PREFER_ECDSA,
		PREFER_RSA,
	}

	private JSchHelper() {
	}

	protected static void reconfigureServerHostKeyOrder(ServerHostKeySortOrder hostKeySortOrder) {
		List<HostKeyType> serverHostKeys = new ArrayList<>(getServerHostKeys());
		if (hostKeySortOrder == ServerHostKeySortOrder.PREFER_ECDSA) {
			Collections.sort(serverHostKeys, CMP_PREFER_ECDSA);
		} else if (hostKeySortOrder == ServerHostKeySortOrder.PREFER_RSA) {
			Collections.sort(serverHostKeys, CMP_PREFER_RSA);
		} else {
			throw new IllegalArgumentException("Unknown host key sort order: " + hostKeySortOrder);
		}

		if (!getServerHostKeys().equals(serverHostKeys)) {
			log.debug("changing server host key order to: " + serverHostKeys);

			List<String> serverHostKeyNames = new ArrayList<>();
			for (HostKeyType serverHostKey : serverHostKeys) {
				serverHostKeyNames.add(serverHostKey.getTypeString());
			}

			String newHostKeyOrder = Utils.join(serverHostKeyNames, SERVER_HOST_KEY_SEPARATOR);
			JSch.setConfig(JSCH_CONFIG_KEY_SERVER_HOST_KEY, newHostKeyOrder);
		}
	}

	protected static void reconfigurePreferredAuthentications() {
		JSch.setConfig(JSCH_CONFIG_KEY_PREFERRED_AUTHENTICATIONS, "publickey");
	}

	protected static void registerLogger() {
		JSch.setLogger(new JSchSlf4JLogger());
	}

	protected static List<HostKeyType> getServerHostKeys() {
		String serverHostKey = JSch.getConfig(JSCH_CONFIG_KEY_SERVER_HOST_KEY);

		List<HostKeyType> hostKeyTypes = new ArrayList<>();
		for (String hostKeyString : Arrays.asList(serverHostKey.split(SERVER_HOST_KEY_SEPARATOR))) {
			hostKeyTypes.add(HostKeyType.byTypeString(hostKeyString));
		}
		return hostKeyTypes;
	}

	public static void configureGlobalSettings() {
		reconfigurePreferredAuthentications();
		registerLogger();
	}
}

@@ -79,38 +79,8 @@
 ys;%0A
-import java.util.Collections;%0A
 impo
@@ -1866,33 +1866,16 @@
 A) %7B%0A%09%09%09
-Collections.sort(
 serverHo
@@ -1872,34 +1872,38 @@
 %09%09serverHostKeys
-, 
+.sort(
 CMP_PREFER_ECDSA
@@ -1982,25 +1982,8 @@
 %0A%09%09%09
-Collections.sort(
 serv
@@ -1992,18 +1992,22 @@
 HostKeys
-, 
+.sort(
 CMP_PREF
@@ -3030,30 +3030,16 @@
 tring : 
-Arrays.asList(
 serverHo
@@ -3077,17 +3077,16 @@
 ARATOR))
-)
  %7B%0A%09%09%09ho

simplify code