/*******************************************************************************
 * Copyright (c) 2011, 2017 WindRiver Corporation and others.
 *
 * This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     WindRiver Corporation - initial API and implementation
 *     IBM Corporation - Ongoing development
 *     Ericsson AB (Pascal Rapicault) - Bug 387115 - Allow to export everything
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.importexport.internal.wizard;

import java.io.*;
import java.net.URI;
import java.util.*;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.importexport.IUDetail;
import org.eclipse.equinox.internal.p2.importexport.VersionIncompatibleException;
import org.eclipse.equinox.internal.p2.importexport.internal.Messages;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
import org.eclipse.equinox.internal.p2.ui.dialogs.ISelectableIUsPage;
import org.eclipse.equinox.internal.p2.ui.dialogs.ProvisioningOperationWizard;
import org.eclipse.equinox.internal.p2.ui.viewers.IUColumnConfig;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.query.CompoundQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.dialogs.PatternFilter;

public class ImportPage extends AbstractImportPage implements ISelectableIUsPage {

	class InstallationContentProvider implements ITreeContentProvider {

		@Override
		public void dispose() {
			//
		}

		@Override
		public Object[] getElements(Object inputElement) {
			return (Object[]) inputElement;
		}

		@Override
		public void inputChanged(Viewer viewer1, Object oldInput, Object newInput) {
			//
		}

		@Override
		public Object[] getChildren(Object parentElement) {
			return new Object[0];
		}

		@Override
		public Object getParent(Object element) {
			return null;
		}

		@Override
		public boolean hasChildren(Object element) {
			return false;
		}

	}

	class InstallationLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider {

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			IInstallableUnit iu = ((IUDetail) element).getIU();
			switch (columnIndex) {
			case 0:
				return getIUNameWithDetail(iu);
			case 1:
				return iu.getVersion().toString();
			case 2:
				return iu.getId();
			default:
				throw new RuntimeException("Should not happen"); //$NON-NLS-1$
			}

		}

		@Override
		public Color getForeground(Object element) {
			if (hasInstalled(ProvUI.getAdapter(element, IInstallableUnit.class)))
				return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
			return null;
		}

		@Override
		public Color getBackground(Object element) {
			return null;
		}
	}

	class P2ImportIUPatternFilter extends PatternFilter {

		boolean checkName, checkVersion, checkId = false;
		String patternString;

		/**
		 * Create a new instance of a AvailableIUPatternFilter
		 */
		public P2ImportIUPatternFilter(IUColumnConfig[] columnConfig) {
			super();
			for (IUColumnConfig columnConfig1 : columnConfig) {
				int field = columnConfig1.getColumnType();
				if (field == IUColumnConfig.COLUMN_ID)
					checkId = true;
				else if (field == IUColumnConfig.COLUMN_NAME)
					checkName = true;
				else if (field == IUColumnConfig.COLUMN_VERSION)
					checkVersion = true;
			}

		}

		@Override
		public boolean isElementSelectable(Object element) {
			return element instanceof IUDetail;
		}

		/*
		 * Overridden to remember the pattern string for an optimization in
		 * isParentMatch
		 */
		@Override
		public void setPattern(String patternString) {
			super.setPattern(patternString);
			this.patternString = patternString;
		}

		/*
		 * Overridden to avoid getting children unless there is actually a filter.
		 */
		@Override
		protected boolean isParentMatch(Viewer viewer1, Object element) {
			if (patternString == null || patternString.length() == 0)
				return true;
			return super.isParentMatch(viewer1, element);
		}

		@Override
		protected boolean isLeafMatch(Viewer viewer1, Object element) {
			String text = null;
			if (element instanceof IUDetail) {
				IInstallableUnit iu = ((IUDetail) element).getIU();
				if (checkName) {
					// Get the iu name in the default locale
					text = iu.getProperty(IInstallableUnit.PROP_NAME, null);
					if (text != null && wordMatches(text))
						return true;
				}
				if (checkId || (checkName && text == null)) {
					text = iu.getId();
					if (wordMatches(text)) {
						return true;
					}
				}
				if (checkVersion) {
					text = iu.getVersion().toString();
					if (wordMatches(text))
						return true;
				}
			}
			return false;
		}

	}

	private List<IUDetail> features;
	private final List<URI> loadRepos = new ArrayList<>();
	private final Map<IUDetail, IUDetail[]> newProposedFeature = new HashMap<>();
	private Button contactAll;
	private Button installLatest;
	private String oldDestination;

	public ImportPage(ProvisioningUI ui, ProvisioningOperationWizard wizard) {
		super("importpage", ui, wizard); //$NON-NLS-1$
		setTitle(Messages.ImportPage_TITLE);
		setDescription(Messages.ImportPage_DESCRIPTION);
	}

	@Override
	protected void createContents(Composite composite) {
		createDestinationGroup(composite, false);
		createInstallationTable(composite);
		createAdditionOptions(composite);
	}

	private void createAdditionOptions(Composite parent) {
		Composite composite = new Composite(parent, SWT.BORDER);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));

		contactAll = new Button(composite, SWT.CHECK);
		contactAll.setText(ProvUIMessages.AvailableIUsPage_ResolveAllCheckbox);

		installLatest = new Button(composite, SWT.CHECK);
		installLatest.setText(Messages.ImportPage_InstallLatestVersion);
		installLatest.setSelection(true);
	}

	@Override
	protected ITreeContentProvider getContentProvider() {
		return new InstallationContentProvider();
	}

	@Override
	protected ITableLabelProvider getLabelProvider() {
		return new InstallationLabelProvider();
	}

	@Override
	protected int getBrowseDialogStyle() {
		return SWT.OPEN;
	}

	@Override
	protected String getDestinationLabel() {
		return Messages.ImportPage_DESTINATION_LABEL;
	}

	@Override
	protected String getDialogTitle() {
		return Messages.ImportPage_FILEDIALOG_TITLE;
	}

	@Override
	protected IUDetail[] getInput() {
		return new IUDetail[0];
	}

	@Override
	protected String getInvalidDestinationMessage() {
		return Messages.ImportPage_DEST_ERROR;
	}

	@Override
	protected void giveFocusToDestination() {
		destinationNameField.setFocus();
	}

	@Override
	protected void updatePageCompletion() {
		super.updatePageCompletion();
		if (isPageComplete())
			getProvisioningWizard().operationSelectionsChanged(this);
	}

	@Override
	protected void handleDestinationChanged(String newDestination) {
		if (validateDestinationGroup()) {
			// p2f file is changed, update the cached data
			if (!newDestination.equals(oldDestination)) {
				loadRepos.clear();
				newProposedFeature.clear();
			}
			InputStream input = null;
			try {
				input = new BufferedInputStream(new FileInputStream(getDestinationValue()));
				features = importexportService.importP2F(input);
				contactAll.setSelection(hasEntriesWithoutRepo());
				viewer.setInput(features.toArray(new IUDetail[features.size()]));
				input.close();
			} catch (VersionIncompatibleException e) {
				MessageDialog.openWarning(getShell(), Messages.ImportPage_TITLE, e.getMessage());
			} catch (FileNotFoundException e) {
				MessageDialog.openError(getShell(), Messages.ImportPage_TITLE, Messages.ImportPage_FILENOTFOUND);
			} catch (IOException e) {
				MessageDialog.openError(getShell(), Messages.ImportPage_TITLE, e.getLocalizedMessage());
			}
		} else
			viewer.setInput(null);
		updatePageCompletion();
	}

	private boolean hasEntriesWithoutRepo() {
		for (IUDetail entry : features) {
			if (entry.getReferencedRepositories().size() == 0)
				return true;
		}
		return false;
	}

	@Override
	protected void setDestinationValue(String selectedFileName) {
		oldDestination = getDestinationValue();
		super.setDestinationValue(selectedFileName);
	}

	@Override
	protected boolean validDestination() {
		File target = new File(getDestinationValue());
		return super.validDestination() && target.exists() && target.canRead();
	}

	@Override
	public Object[] getCheckedIUElements() {
		Object[] checked = viewer.getCheckedElements();
		List<IUDetail> checkedFeatures = new ArrayList<>(checked.length);
		boolean useLatest = installLatest.getSelection();
		for (Object checked1 : checked) {
			IUDetail feature = (IUDetail) checked1;
			IUDetail[] existingFeatures = newProposedFeature.get(feature);
			if (existingFeatures == null) {
				checkedFeatures.add(feature);
			} else {
				IUDetail matchPolicy = null;
				for (IUDetail f : existingFeatures) {
					if (matchPolicy == null) {
						matchPolicy = f;
					} else {
						if (matchPolicy.getIU().getVersion().compareTo(f.getIU().getVersion()) < 0) {
							if (useLatest) {
								matchPolicy = f;
							}
						} else {
							if (!useLatest) {
								matchPolicy = f;
							}
						}
					}
				}
				if (matchPolicy != null) {
					checkedFeatures.add(matchPolicy);
				}
			}
		}
		return checkedFeatures.toArray(new IUDetail[checkedFeatures.size()]);
	}

	@Override
	public Object[] getSelectedIUElements() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setCheckedElements(Object[] elements) {
		new UnsupportedOperationException();
	}

	public ProvisioningContext getProvisioningContext() {
		if (agent != null) {
			Object[] checked = viewer.getCheckedElements();
			List<URI> referredRepos = new ArrayList<>(checked.length);
			for (Object checkItem : checked) {
				IUDetail feature = (IUDetail) checkItem;
				for (URI uri : feature.getReferencedRepositories()) {
					referredRepos.add(uri);
				}
			}
			ProvisioningContext context = new ProvisioningContext(agent);
			if (!contactAll.getSelection()) {
				context.setArtifactRepositories(referredRepos.toArray(new URI[referredRepos.size()]));
				context.setMetadataRepositories(referredRepos.toArray(new URI[referredRepos.size()]));
			}
			return context;
		}
		return null;
	}

	public boolean hasUnloadedRepo() {
		for (Object checked : viewer.getCheckedElements()) {
			IUDetail feature = (IUDetail) checked;
			for (URI uri : feature.getReferencedRepositories())
				if (!loadRepos.contains(uri))
					return true;
		}
		return false;
	}

	class GetCheckedElement implements Runnable {
		Object[] checkedElements = null;

		@Override
		public void run() {
			checkedElements = viewer.getCheckedElements();
		}
	}

	public Object[] getChecked() {
		if (Display.findDisplay(Thread.currentThread()) != null)
			return viewer.getCheckedElements();
		GetCheckedElement get = new GetCheckedElement();
		Display.getDefault().syncExec(get);
		return get.checkedElements;
	}

	public void recompute(IProgressMonitor monitor) throws InterruptedException {
		SubMonitor sub = SubMonitor.convert(monitor, Messages.ImportPage_QueryFeaturesJob, 1000);
		if (agent != null) {
			IMetadataRepositoryManager metaManager = agent.getService(IMetadataRepositoryManager.class);
			IArtifactRepositoryManager artifactManager = agent.getService(IArtifactRepositoryManager.class);
			Object[] checked = getChecked();
			sub.setWorkRemaining(100 * checked.length);
			for (Object item : checked) {
				IUDetail feature = (IUDetail) item;
				if (!newProposedFeature.containsKey(feature)) {
					if (sub.isCanceled())
						throw new InterruptedException();
					SubMonitor sub2 = sub.newChild(100, SubMonitor.SUPPRESS_ALL_LABELS);
					sub2.setWorkRemaining(feature.getReferencedRepositories().size() * 500 + 100);
					List<IRepository<IInstallableUnit>> repos = new ArrayList<>();
					for (URI uri : feature.getReferencedRepositories()) {
						if (!metaManager.contains(uri)) {
							metaManager.addRepository(uri);
						}
						metaManager.setEnabled(uri, true);
						try {
							repos.add(metaManager.loadRepository(uri, sub2.newChild(500)));
						} catch (ProvisionException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (OperationCanceledException e) {
							throw new InterruptedException(e.getLocalizedMessage());
						}
						if (!artifactManager.contains(uri)) {
							artifactManager.addRepository(uri);
						}
						artifactManager.setEnabled(uri, true);
					}
					if (sub2.isCanceled())
						throw new InterruptedException();
					// don't suppress this warning as it will cause build-time warning
					// see bug 423628. Find a way to change the code to not produce
					// the warning.
					Set<IInstallableUnit> result = new CompoundQueryable<IInstallableUnit>(
							repos.toArray(new IRepository[repos.size()]))
									.query(QueryUtil.createIUQuery(feature.getIU().getId(),
											new VersionRange(feature.getIU().getVersion(), true, null, false)),
											sub2.newChild(100))
									.toSet();
					List<IUDetail> existingFeatures = new ArrayList<>(result.size());
					for (IInstallableUnit iu : result) {
						existingFeatures.add(new IUDetail(iu, feature.getReferencedRepositories()));
					}
					newProposedFeature.put(feature, existingFeatures.toArray(new IUDetail[existingFeatures.size()]));
				} else {
					if (sub.isCanceled())
						throw new InterruptedException();
					sub.worked(100);
				}
			}
		}
	}

	@Override
	protected PatternFilter getPatternFilter() {
		return new P2ImportIUPatternFilter(getColumnConfig());
	}
}