/*******************************************************************************
 * Copyright (c) 2014, 2018 Red Hat Inc. and others.
 * 
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Red Hat - Initial Contribution
 *******************************************************************************/

package org.eclipse.linuxtools.internal.docker.ui.wizards;

import static org.eclipse.linuxtools.docker.core.EnumDockerConnectionSettings.UNIX_SOCKET;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.validation.MultiValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.wizard.WizardPageSupport;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
import org.eclipse.linuxtools.docker.core.DockerException;
import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.ui.Activator;
import org.eclipse.linuxtools.internal.docker.core.DockerConnection;
import org.eclipse.linuxtools.internal.docker.core.TCPConnectionSettings;
import org.eclipse.linuxtools.internal.docker.core.UnixSocketConnectionSettings;
import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;

import com.spotify.docker.client.exceptions.DockerCertificateException;

/**
 * {@link WizardPage} to edit an {@link IDockerConnection}
 *
 */
public class EditDockerConnectionPage extends WizardPage {

	private final DataBindingContext dbc;

	private final EditDockerConnectionPageModel model;

	/**
	 * Constructor.
	 * 
	 * @param currentConnection
	 *            the {@link IDockerConnection} to edit
	 */
	public EditDockerConnectionPage(final IDockerConnection currentConnection) {
		super("DockerConnectionPage", //$NON-NLS-1$
				WizardMessages.getString("DockerConnectionPage.title"), //$NON-NLS-1$
				SWTImagesFactory.DESC_BANNER_REPOSITORY);
		setMessage(WizardMessages.getString("DockerConnectionPage.msg")); //$NON-NLS-1$
		this.model = new EditDockerConnectionPageModel(currentConnection);
		this.dbc = new DataBindingContext();
	}

	@Override
	public void createControl(final Composite parent) {
		final ScrolledComposite scrollTop = new ScrolledComposite(parent,
				SWT.H_SCROLL | SWT.V_SCROLL);
		scrollTop.setExpandVertical(true);
		scrollTop.setExpandHorizontal(true);

		final Composite container = new Composite(scrollTop, SWT.NONE);
		GridLayoutFactory.fillDefaults().numColumns(1).applyTo(container);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.applyTo(container);
		createConnectionSettingsContainer(container);
		// attach the Databinding context status to this wizard page.
		WizardPageSupport.create(this, this.dbc);

		scrollTop.setContent(container);
		Point point = container.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		scrollTop.setSize(point);
		scrollTop.setMinSize(point);
		setControl(container);
	}

	@Override
	public void dispose() {
		if (dbc != null) {
			dbc.dispose();
		}
		super.dispose();
	}

	/**
	 * Creates the connection settings container, where the user can choose how
	 * to connect to the docker daemon (using sockets or TCP with SSL - or not)
	 * 
	 * @param parent
	 *            the parent container (ie, the main container in the preference
	 *            page)
	 */
	@SuppressWarnings("unchecked")
	private void createConnectionSettingsContainer(final Composite parent) {
		final int COLUMNS = 3;
		final int INDENT = 20;
		final Composite container = new Composite(parent, SWT.NONE);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(1, 1)
				.grab(true, false).applyTo(container);
		GridLayoutFactory.fillDefaults().numColumns(COLUMNS).margins(6, 6)
				.spacing(10, 2).applyTo(container);

		// Connection name
		final Label connectionNameLabel = new Label(container, SWT.NONE);
		connectionNameLabel.setText(
				WizardMessages.getString("DockerConnectionPage.nameLabel")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.applyTo(connectionNameLabel);
		final Text connectionNameText = new Text(container, SWT.BORDER);
		connectionNameText.setToolTipText(
				WizardMessages.getString("DockerConnectionPage.nameTooltip")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.grab(true, false).span(2, 1).applyTo(connectionNameText);

		// Unix socket
		final Button unixSocketBindingModeButton = new Button(container,
				SWT.RADIO);
		unixSocketBindingModeButton.setText(
				WizardMessages.getString("DockerConnectionPage.unixSocket")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).indent(0, 10)
				.span(COLUMNS, 1).applyTo(unixSocketBindingModeButton);

		final Label unixSocketPathLabel = new Label(container, SWT.NONE);
		unixSocketPathLabel.setText(
				WizardMessages.getString("DockerConnectionPage.location")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.indent(INDENT, 0).applyTo(unixSocketPathLabel);
		final Text unixSocketPathText = new Text(container, SWT.BORDER);
		unixSocketPathText.setToolTipText(WizardMessages
				.getString("DockerConnectionPage.unixPathTooltip")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.grab(true, false).applyTo(unixSocketPathText);

		final Button unixSocketPathBrowseButton = new Button(container,
				SWT.BUTTON1);
		unixSocketPathBrowseButton.setText(
				WizardMessages.getString("DockerConnectionPage.browseButton")); //$NON-NLS-1$
		unixSocketPathBrowseButton
				.addSelectionListener(onBrowseUnixSocketPath());
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.applyTo(unixSocketPathBrowseButton);

		// TCP connection
		final Button tcpConnectionBindingModeButton = new Button(container,
				SWT.RADIO);
		tcpConnectionBindingModeButton.setText(
				WizardMessages.getString("DockerConnectionPage.tcpConnection")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.span(COLUMNS, 1).applyTo(tcpConnectionBindingModeButton);

		final Label tcpHostLabel = new Label(container, SWT.NONE);
		tcpHostLabel.setText(
				WizardMessages.getString("DockerConnectionPage.hostLabel")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.indent(INDENT, 0).applyTo(tcpHostLabel);

		final Text tcpHostText = new Text(container, SWT.BORDER);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(2, 1)
				.grab(true, false).applyTo(tcpHostText);

		final Button tcpAuthButton = new Button(container, SWT.CHECK);
		tcpAuthButton.setText(
				WizardMessages.getString("DockerConnectionPage.tcpAuthButton")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.indent(INDENT, 0).span(3, 1).applyTo(tcpAuthButton);

		final Label tcpCertPathLabel = new Label(container, SWT.NONE);
		tcpCertPathLabel.setText(
				WizardMessages.getString("DockerConnectionPage.tcpPathLabel")); //$NON-NLS-1$
		tcpCertPathLabel.setToolTipText(WizardMessages
				.getString("DockerConnectionPage.tcpPathTooltip")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.indent(INDENT * 2, 0).applyTo(tcpCertPathLabel);
		final Text tcpCertPathText = new Text(container, SWT.BORDER);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.grab(true, false).applyTo(tcpCertPathText);
		final Button tcpCertPathBrowseButton = new Button(container,
				SWT.BUTTON1);
		tcpCertPathBrowseButton.setText(
				WizardMessages.getString("DockerConnectionPage.browseButton")); //$NON-NLS-1$
		tcpCertPathBrowseButton.addSelectionListener(onBrowseTcpCertPath());
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.applyTo(tcpCertPathBrowseButton);

		// the 'test connection' button
		final Button testConnectionButton = new Button(container, SWT.NONE);
		testConnectionButton.setText(WizardMessages
				.getString("DockerConnectionPage.testConnection")); //$NON-NLS-1$
		GridDataFactory.fillDefaults().span(3, 1)
				.indent(0, 10).align(SWT.END, SWT.CENTER)
				.applyTo(testConnectionButton);
		testConnectionButton
				.addSelectionListener(onTestConnectionButtonSelection());

		// observe
		final IObservableValue<String> connectionNameModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.CONNECTION_NAME)
				.observe(model);
		final IObservableValue<Boolean> unixSocketBindingModeModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.UNIX_SOCKET_BINDING_MODE)
				.observe(model);
		final IObservableValue<String> unixSocketPathModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.UNIX_SOCKET_PATH)
				.observe(model);

		final IObservableValue<Boolean> tcpConnectionBindingModeModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.TCP_CONNECTION_BINDING_MODE)
				.observe(model);
		final IObservableValue<String> tcpCertPathModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.TCP_CERT_PATH)
				.observe(model);
		final IObservableValue<Boolean> tcpTlsVerifyModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.TCP_TLS_VERIFY)
				.observe(model);
		final IObservableValue<String> tcpHostModelObservable = BeanProperties
				.value(EditDockerConnectionPageModel.class,
						EditDockerConnectionPageModel.TCP_HOST)
				.observe(model);

		// group controls to easily enable/disable them
		final Control[] unixSocketControls = new Control[] { unixSocketPathText,
				unixSocketPathLabel, unixSocketPathBrowseButton };
		final Control[] tcpConnectionControls = new Control[] { tcpHostText,
				tcpHostLabel, tcpAuthButton };
		final Control[] tcpAuthControls = new Control[] { tcpCertPathText,
				tcpCertPathLabel, tcpCertPathBrowseButton };
		unixSocketBindingModeModelObservable.addChangeListener(
				onUnixSocketBindingSelection(unixSocketControls));
		tcpConnectionBindingModeModelObservable.addChangeListener(
				onTcpConnectionBindingSelection(tcpConnectionControls,
						tcpAuthControls));
		tcpTlsVerifyModelObservable
				.addValueChangeListener(onTcpAuthSelection(tcpAuthControls));

		// bind controls to model
		dbc.bindValue(
				WidgetProperties.text(SWT.Modify).observe(connectionNameText),
				connectionNameModelObservable);
		dbc.bindValue(
				WidgetProperties.selection()
						.observe(unixSocketBindingModeButton),
				unixSocketBindingModeModelObservable);
		dbc.bindValue(
				WidgetProperties.text(SWT.Modify).observe(unixSocketPathText),
				unixSocketPathModelObservable);
		dbc.bindValue(
				WidgetProperties.selection()
						.observe(tcpConnectionBindingModeButton),
				tcpConnectionBindingModeModelObservable);
		dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(tcpHostText),
				tcpHostModelObservable);
		dbc.bindValue(WidgetProperties.selection().observe(tcpAuthButton),
				tcpTlsVerifyModelObservable);
		dbc.bindValue(
				WidgetProperties.text(SWT.Modify).observe(tcpCertPathText),
				tcpCertPathModelObservable);
		// validations will be performed when the user changes the value
		// only, not at the dialog opening
		dbc.addValidationStatusProvider(
				new ConnectionNameValidator(connectionNameModelObservable,
						this.model.getInitialConnectionName()));
		dbc.addValidationStatusProvider(
				new UnixSocketValidator(unixSocketBindingModeModelObservable,
						unixSocketPathModelObservable));
		dbc.addValidationStatusProvider(
				new TcpHostValidator(tcpConnectionBindingModeModelObservable,
						tcpHostModelObservable));
		dbc.addValidationStatusProvider(new TcpCertificatesValidator(
				tcpConnectionBindingModeModelObservable,
				tcpTlsVerifyModelObservable, tcpCertPathModelObservable));

		// give focus to connectionName text at first
		connectionNameText.setFocus();
		// set widgets initial state
		updateWidgetsState(unixSocketControls, tcpConnectionControls,
				tcpAuthControls);
	}

	private SelectionListener onBrowseUnixSocketPath() {
		return SelectionListener.widgetSelectedAdapter(e -> {
			final FileDialog fileDialog = new FileDialog(getShell());
			final String selectedPath = fileDialog.open();
			if (selectedPath != null) {
				model.setUnixSocketPath("unix://" + selectedPath); //$NON-NLS-1$
			}
		});
	}

	private SelectionListener onBrowseTcpCertPath() {
		return SelectionListener.widgetSelectedAdapter(e -> {
			final DirectoryDialog directoryDialog = new DirectoryDialog(
					getShell());
			directoryDialog.setFilterPath(model.getTcpCertPath());
			final String selectedPath = directoryDialog.open();
			if (selectedPath != null) {
				model.setTcpCertPath(selectedPath);
			}
		});
	}

	private void updateWidgetsState(final Control[] unixSocketControls,
			final Control[] tcpConnectionControls,
			final Control[] tcpAuthControls) {
		setWidgetsEnabled(
				model.isTcpConnectionBindingMode() && model.isTcpTLSVerify(),
				tcpAuthControls);
		setWidgetsEnabled(model.isTcpConnectionBindingMode(),
				tcpConnectionControls);
		setWidgetsEnabled(model.isUnixSocketBindingMode(), unixSocketControls);
	}

	private IChangeListener onUnixSocketBindingSelection(
			final Control[] unixSocketControls) {
		return event -> setWidgetsEnabled(model.isUnixSocketBindingMode(),
				unixSocketControls);
	}

	private IChangeListener onTcpConnectionBindingSelection(
			final Control[] tcpConnectionControls,
			final Control[] tcpAuthControls) {
		return event -> {
			setWidgetsEnabled(model.isTcpConnectionBindingMode()
					&& model.isTcpTLSVerify(), tcpAuthControls);
			// and give focus to the first given control (if applicable)
			setWidgetsEnabled(model.isTcpConnectionBindingMode(),
					tcpConnectionControls);
		};
	}

	private IValueChangeListener<Boolean> onTcpAuthSelection(
			final Control[] tcpAuthControls) {
		return event -> setWidgetsEnabled(
				model.isTcpConnectionBindingMode() && model.isTcpTLSVerify(),
				tcpAuthControls);
	}

	private void setWidgetsEnabled(final boolean enabled,
			final Control... controls) {
		for (Control control : controls) {
			control.setEnabled(enabled);
		}
		// set the focus on the fist element of the group.
		if (enabled) {
			for (Control control : controls) {
				if (control instanceof Text) {
					control.setFocus();
					break;
				}
			}
		}
	}

	/**
	 * Verifies that the given connection settings work by trying to connect to
	 * the target Docker daemon
	 * 
	 * @return
	 */
	private SelectionListener onTestConnectionButtonSelection() {
		return new SelectionAdapter() {

			@Override
			public void widgetSelected(final SelectionEvent event) {
				try {
					getWizard().getContainer().run(true, false, monitor -> {
						monitor.beginTask(WizardMessages.getString(
										"DockerConnectionPage.pingTask"), //$NON-NLS-1$
								IProgressMonitor.UNKNOWN);
						try (DockerConnection dockerConnection = getDockerConnection()) {
							dockerConnection.open(false);
							// ping succeeded
							displaySuccessDialog();
						} catch (DockerException e) {
							// only log if there's an underlying cause.
							if (e.getCause() != null) {
								displayErrorDialog(e.getCause());
							} else {
								displayErrorDialog(e);
							}
						}
					});
				} catch (InvocationTargetException | InterruptedException o_O) {
					Activator.log(o_O);
				}

			}

			private void displaySuccessDialog() {
				displayDialog(
						WizardMessages
								.getString("DockerConnectionPage.success"), //$NON-NLS-1$
						WizardMessages
								.getString("DockerConnectionPage.pingSuccess"), //$NON-NLS-1$
						SWT.ICON_INFORMATION, new String[] { WizardMessages
								.getString("DockerConnectionPage.ok") } //$NON-NLS-1$
				);
			}

			private void displayErrorDialog(final Throwable cause) {
				displayDialog(
						WizardMessages
								.getString("DockerConnectionPage.failure"), //$NON-NLS-1$
						WizardMessages
								.getFormattedString(
										"DockerConnectionPage.pingFailure", //$NON-NLS-1$
										cause.getMessage()),
						SWT.ICON_ERROR, new String[] { WizardMessages
								.getString("DockerConnectionPage.ok") } //$NON-NLS-1$
				);
			}

			private void displayDialog(final String dialogTitle,
					final String dialogMessage, final int icon,
					final String[] buttonLabels) {
				Display.getDefault()
						.syncExec(() -> new MessageDialog(
								PlatformUI.getWorkbench()
										.getActiveWorkbenchWindow().getShell(),
								dialogTitle, null, dialogMessage, icon,
								buttonLabels, 0).open());
			}

		};
	}

	/**
	 * Opens a new {@link DockerConnection} using the settings of this
	 * {@link EditDockerConnectionPage}.
	 * 
	 * @return
	 * @throws DockerCertificateException
	 */
	protected DockerConnection getDockerConnection() {
		if (model.getBindingMode() == UNIX_SOCKET) {
			return new DockerConnection.Builder()
					.name(model.getConnectionName())
					.unixSocketConnection(new UnixSocketConnectionSettings(
							model.getUnixSocketPath()));
		} else {
			return new DockerConnection.Builder()
					.name(model.getConnectionName())
					.tcpConnection(new TCPConnectionSettings(model.getTcpHost(),
							model.getTcpCertPath()));
		}
	}

	private static class ConnectionNameValidator extends MultiValidator {

		private final IObservableValue<String> connectionNameModelObservable;

		private final String initialConnectionName;

		public ConnectionNameValidator(
				final IObservableValue<String> connectionNameModelObservable,
				final String initialConnectionName) {
			this.connectionNameModelObservable = connectionNameModelObservable;
			this.initialConnectionName = initialConnectionName;
		}

		@Override
		public IObservableList<IObservable> getTargets() {
			IObservableList<IObservable> targets = new WritableList<>();
			targets.add(connectionNameModelObservable);
			return targets;
		}

		@Override
		protected IStatus validate() {
			final String connectionName = this.connectionNameModelObservable
					.getValue();
			if (connectionName == null || connectionName.isEmpty()) {
				return ValidationStatus.error(WizardMessages.getString(
						"DockerConnectionPage.validation.missingConnectionName.msg")); //$NON-NLS-1$
			} else if (!connectionName.equals(this.initialConnectionName)
					&& DockerConnectionManager.getInstance()
							.findConnection(connectionName) != null) {
				return ValidationStatus.error(WizardMessages.getString(
						"DockerConnectionPage.validation.duplicateConnectionName.msg")); //$NON-NLS-1$
			}
			return ValidationStatus.ok();
		}
	}

	private static class UnixSocketValidator extends MultiValidator {

		private final IObservableValue<Boolean> unixSocketBindingModeModelObservable;
		private final IObservableValue<String> unixSocketPathModelObservable;

		public UnixSocketValidator(
				final IObservableValue<Boolean> unixSocketBindingModeModelObservable,
				final IObservableValue<String> unixSocketPathModelObservable) {
			this.unixSocketBindingModeModelObservable = unixSocketBindingModeModelObservable;
			this.unixSocketPathModelObservable = unixSocketPathModelObservable;
		}

		@Override
		public IObservableList<IObservable> getTargets() {
			IObservableList<IObservable> targets = new WritableList<>();
			targets.add(unixSocketPathModelObservable);
			return targets;
		}

		@Override
		protected IStatus validate() {
			final Boolean unixSocketBindingMode = this.unixSocketBindingModeModelObservable
					.getValue();
			final String unixSocketPath = this.unixSocketPathModelObservable
					.getValue();
			if (unixSocketBindingMode) {
				if (unixSocketPath == null || unixSocketPath.isEmpty()) {
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.missingUnixSocket.msg")); //$NON-NLS-1$
				}
				try {
					final URI unixSocketURI = new URI(unixSocketPath);
					if (unixSocketURI.getScheme() != null
							&& !unixSocketURI.getScheme().equals("unix")) { //$NON-NLS-1$
						return ValidationStatus.error(WizardMessages.getString(
								"DockerConnectionPage.validation.invalidUnixSocketScheme.msg")); //$NON-NLS-1$
					}
					if (unixSocketURI.getPath() != null) {
						final File unixSocket = new File(
								unixSocketURI.getPath());
						if (!unixSocket.exists()) {
							return ValidationStatus
									.error(WizardMessages.getString(
											"DockerConnectionPage.validation.invalidUnixSocketPath.msg")); //$NON-NLS-1$
						} else if (!unixSocket.canRead()
								|| !unixSocket.canWrite()) {
							return ValidationStatus
									.error(WizardMessages.getString(
											"DockerConnectionPage.validation.unreadableUnixSocket.msg")); //$NON-NLS-1$
						}
					} else {
						return ValidationStatus.error(WizardMessages.getString(
								"DockerConnectionPage.validation.invalidUnixSocketPath.msg")); //$NON-NLS-1$

					}
				} catch (URISyntaxException e) {
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.invalidUnixSocketPath.msg")); //$NON-NLS-1$

				}
			}
			return ValidationStatus.ok();
		}

	}

	private static class TcpHostValidator extends MultiValidator {

		private final IObservableValue<Boolean> tcpConnectionBindingModeModelObservable;
		private final IObservableValue<String> tcpHostModelObservable;

		public TcpHostValidator(
				final IObservableValue<Boolean> tcpConnectionBindingModeModelObservable,
				final IObservableValue<String> tcpHostModelObservable) {
			this.tcpConnectionBindingModeModelObservable = tcpConnectionBindingModeModelObservable;
			this.tcpHostModelObservable = tcpHostModelObservable;
		}

		@Override
		public IObservableList<IObservable> getTargets() {
			IObservableList<IObservable> targets = new WritableList<>();
			targets.add(tcpHostModelObservable);
			return targets;
		}

		@Override
		protected IStatus validate() {
			final Boolean tcpConnectionBindingMode = this.tcpConnectionBindingModeModelObservable
					.getValue();
			final String tcpHost = this.tcpHostModelObservable.getValue();
			if (tcpConnectionBindingMode) {
				if (tcpHost == null || tcpHost.isEmpty()) {
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.missingTcpConnectionURI.msg")); //$NON-NLS-1$
				}
				try {
					final URI uri = new URI(tcpHost);
					final String scheme = uri.getScheme() != null
							? uri.getScheme().toLowerCase() : null;
					final String host = uri.getHost();
					final int port = uri.getPort();
					if (scheme != null
							&& !(scheme.equals("tcp") || scheme.equals("http") //$NON-NLS-1$ //$NON-NLS-2$
									|| scheme.equals("https"))) { //$NON-NLS-1$
						return ValidationStatus.error(WizardMessages.getString(
								"DockerConnectionPage.validation.invalidTcpConnectionScheme.msg")); //$NON-NLS-1$
					} else if (host == null) {
						return ValidationStatus.error(WizardMessages.getString(
								"DockerConnectionPage.validation.invalidTcpConnectionHost.msg")); //$NON-NLS-1$

					} else if (port == -1) {
						return ValidationStatus.error(WizardMessages.getString(
								"DockerConnectionPage.validation.invalidTcpConnectionPort.msg")); //$NON-NLS-1$

					}
				} catch (URISyntaxException e) {
					// URI is not valid
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.invalidTcpConnectionURI.msg")); //$NON-NLS-1$
				}
			}
			return ValidationStatus.ok();
		}

	}

	private static class TcpCertificatesValidator extends MultiValidator {

		private final IObservableValue<Boolean> tcpConnectionBindingModeModelObservable;
		private final IObservableValue<Boolean> tcpTlsVerifyModelObservable;
		private final IObservableValue<String> tcpCertPathModelObservable;

		public TcpCertificatesValidator(
				final IObservableValue<Boolean> tcpConnectionBindingModeModelObservable,
				final IObservableValue<Boolean> tcpTlsVerifyModelObservable,
				final IObservableValue<String> tcpCertPathModelObservable) {
			this.tcpConnectionBindingModeModelObservable = tcpConnectionBindingModeModelObservable;
			this.tcpTlsVerifyModelObservable = tcpTlsVerifyModelObservable;
			this.tcpCertPathModelObservable = tcpCertPathModelObservable;
		}

		@Override
		public IObservableList<IObservable> getTargets() {
			IObservableList<IObservable> targets = new WritableList<>();
			targets.add(tcpCertPathModelObservable);
			return targets;
		}

		@Override
		protected IStatus validate() {
			final Boolean tcpConnectionBindingMode = this.tcpConnectionBindingModeModelObservable
					.getValue();
			final Boolean tcpTlsVerify = this.tcpTlsVerifyModelObservable
					.getValue();
			final String tcpCertPath = this.tcpCertPathModelObservable
					.getValue();
			if (tcpConnectionBindingMode && tcpTlsVerify) {
				if (tcpCertPath == null || tcpCertPath.isEmpty()) {
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.missingTcpCertPath.msg")); //$NON-NLS-1$
				}
				final File tcpCert = new File(tcpCertPath);
				if (!tcpCert.exists()) {
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.invalidTcpCertPath.msg")); //$NON-NLS-1$
				} else if (!tcpCert.canRead() || !tcpCert.canRead()) {
					return ValidationStatus.error(WizardMessages.getString(
							"DockerConnectionPage.validation.unreadableTcpCertPath.msg")); //$NON-NLS-1$
				}
			}
			return ValidationStatus.ok();
		}

	}

}
