/*******************************************************************************
 * Copyright (c) 2008, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Alena Laskavaia - Bug 432399 - Export feature not exporting empty folders
 *******************************************************************************/
package org.eclipse.pde.internal.build.publisher;

import java.io.File;
import java.util.*;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.PatternSet.NameEntry;
import org.apache.tools.ant.types.selectors.FilenameSelector;
import org.apache.tools.ant.types.selectors.OrSelector;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.p2.publisher.PublisherInfo;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.build.*;
import org.eclipse.pde.internal.build.builder.ModelBuildScriptGenerator;
import org.eclipse.pde.internal.build.tasks.TaskMessages;

public class GatherFeatureTask extends AbstractPublisherTask {
	private String buildResultFolder = null;
	private String targetFolder = null;
	private String licenseDirectory = null;

	@Override
	public void execute() throws BuildException {
		GatheringComputer computer = createFeatureComputer();

		GatherFeatureAction action = null;
		if (targetFolder == null)
			action = new GatherFeatureAction(new File(baseDirectory), new File(buildResultFolder));
		else {
			action = new GatherFeatureAction(new File(baseDirectory), new File(targetFolder));
		}
		action.setComputer(computer);
		setGroupId(action);

		FeatureRootAdvice advice = createRootAdvice();
		action.setRootAdvice(advice);
		PublisherInfo info = getPublisherInfo();
		info.addAdvice(advice);
		BuildPublisherApplication application = createPublisherApplication();
		application.addAction(action);
		try {
			application.run(info);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void setGroupId(GatherFeatureAction action) {
		Properties properties = getBuildProperties();
		if (properties.containsKey(IBuildPropertiesConstants.PROPERTY_P2_GROUP_ID))
			action.setGroupId(properties.getProperty(IBuildPropertiesConstants.PROPERTY_P2_GROUP_ID));
	}

	protected GatheringComputer createFeatureComputer() {
		Properties properties = getBuildProperties();

		String include = (String) properties.get(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES);
		String exclude = (String) properties.get(IBuildPropertiesConstants.PROPERTY_BIN_EXCLUDES);

		if (include == null)
			return null;

		if (targetFolder != null) {
			FileSet fileSet = new FileSet();
			fileSet.setProject(getProject());
			fileSet.setDir(new File(targetFolder));
			NameEntry includeEntry = fileSet.createInclude();
			includeEntry.setName("**"); //$NON-NLS-1$

			String[] files = fileSet.getDirectoryScanner().getIncludedFiles();
			if (files != null && files.length > 0) {
				GatheringComputer computer = new GatheringComputer();
				computer.addFiles(targetFolder, files);
				return computer;
			}
			return null;
		}

		GatheringComputer computer = new GatheringComputer();

		if (licenseDirectory != null) {
			try {
				// Default includes and excludes for binary license features
				String licenseInclude = "**"; //$NON-NLS-1$
				String licenseExclude = "META-INF/"; //$NON-NLS-1$

				// Read build.properties from license feature for source features
				if (new File(licenseDirectory, IPDEBuildConstants.PROPERTIES_FILE).exists()) {
					Properties licenseProperties = AbstractScriptGenerator.readProperties(licenseDirectory, IPDEBuildConstants.PROPERTIES_FILE, IStatus.WARNING);
					licenseInclude = (String) licenseProperties.get(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES);
					licenseExclude = (String) licenseProperties.get(IBuildPropertiesConstants.PROPERTY_BIN_EXCLUDES);
				}
				licenseExclude = (licenseExclude != null ? licenseExclude + "," : "") + IPDEBuildConstants.LICENSE_DEFAULT_EXCLUDES; //$NON-NLS-1$//$NON-NLS-2$

				FileSet licenseFiles = createFileSet(licenseDirectory, licenseInclude, licenseExclude);
				computer.addFiles(licenseDirectory, licenseFiles.getDirectoryScanner().getIncludedFiles());
			} catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		FileSet fileSet = createFileSet(buildResultFolder, include, exclude);
		DirectoryScanner directoryScanner = fileSet.getDirectoryScanner();
		computer.addFiles(buildResultFolder, directoryScanner.getIncludedFiles());
		computer.addFiles(buildResultFolder, directoryScanner.getIncludedDirectories());
		return computer;
	}

	private FileSet createFileSet(String folder, String includes, String excludes) {
		FileSet fileSet = new FileSet();
		fileSet.setProject(getProject());
		fileSet.setDir(new File(folder));
		String[] splitIncludes = Utils.getArrayFromString(includes);
		for (int i = 0; i < splitIncludes.length; i++) {
			String entry = splitIncludes[i];
			if (entry.equals(ModelBuildScriptGenerator.DOT))
				continue;

			NameEntry fileInclude = fileSet.createInclude();
			fileInclude.setName(entry);
		}

		String[] splitExcludes = Utils.getArrayFromString(excludes);
		for (int i = 0; i < splitExcludes.length; i++) {
			NameEntry fileExclude = fileSet.createExclude();
			fileExclude.setName(splitExcludes[i]);
		}
		return fileSet;
	}

	private String reorderConfig(String config) {
		String[] parsed = Utils.getArrayFromString(config, "."); //$NON-NLS-1$
		return parsed[1] + '.' + parsed[0] + '.' + parsed[2];
	}

	protected FeatureRootAdvice createRootAdvice() {
		FeatureRootAdvice advice = new FeatureRootAdvice();

		Map<String, Map<String, String>> configMap = Utils.processRootProperties(getBuildProperties(), true);
		for (Iterator<String> iterator = configMap.keySet().iterator(); iterator.hasNext();) {
			String config = iterator.next();
			Map<String, String> rootMap = configMap.get(config);
			if (config.equals(Utils.ROOT_COMMON))
				config = ""; //$NON-NLS-1$
			else
				config = reorderConfig(config);
			GatheringComputer computer = new GatheringComputer();
			Map<FileSet, String> configFileSets = new HashMap<FileSet, String>();
			ArrayList<String> permissionsKeys = new ArrayList<String>();
			for (Iterator<String> rootEntries = rootMap.keySet().iterator(); rootEntries.hasNext();) {
				String key = rootEntries.next();
				if (key.startsWith(Utils.ROOT_PERMISSIONS)) {
					permissionsKeys.add(key);
					continue;
				} else if (key.equals(Utils.ROOT_LINK)) {
					advice.addLinks(config, rootMap.get(key));
					continue;
				} else {
					//files!
					String fileList = rootMap.get(key);
					String[] files = Utils.getArrayFromString(fileList, ","); //$NON-NLS-1$
					for (int i = 0; i < files.length; i++) {
						String file = files[i];
						String fromDir = baseDirectory;
						File base = null;
						if (file.startsWith("absolute:")) { //$NON-NLS-1$
							file = file.substring(9);
							fromDir = null;
						} else if (file.startsWith("license:")) { //$NON-NLS-1$
							if (licenseDirectory == null) {
								throw new BuildException(NLS.bind(TaskMessages.error_licenseRootWithoutLicenseRef, baseDirectory));
							}
							file = file.substring(8);
							fromDir = licenseDirectory;
						}
						if (file.startsWith("file:")) { //$NON-NLS-1$
							File temp = fromDir != null ? new File(fromDir, file.substring(5)) : new File(file.substring(5));
							base = temp.getParentFile();
							file = temp.getName();
						} else {
							base = fromDir != null ? new File(fromDir, file) : new File(file);
							file = "**"; //$NON-NLS-1$
						}

						if (base.exists()) {
							FileSet fileset = new FileSet();
							fileset.setProject(getProject());
							fileset.setDir(base);
							NameEntry include = fileset.createInclude();
							include.setName(file);

							String[] found = fileset.getDirectoryScanner().getIncludedFiles();
							for (int k = 0; k < found.length; k++) {
								if (key.length() > 0)
									computer.addFile(key + "/" + found[k], new File(base, found[k])); //$NON-NLS-1$
								else
									computer.addFile(base.getAbsolutePath(), found[k]);
							}
							configFileSets.put(fileset, key);
						}
					}
				}
			}
			if (computer.size() > 0)
				advice.addRootfiles(config, computer);

			//do permissions, out of the configFileSets, select the files to change permissions on.
			for (Iterator<String> p = permissionsKeys.iterator(); p.hasNext();) {
				String permissionKey = p.next();
				String permissionString = rootMap.get(permissionKey);
				String[] names = Utils.getArrayFromString(permissionString);

				OrSelector orSelector = new OrSelector();
				orSelector.setProject(getProject());
				for (int i = 0; i < names.length; i++) {
					FilenameSelector nameSelector = new FilenameSelector();
					nameSelector.setProject(getProject());
					nameSelector.setName(names[i]);
					orSelector.addFilename(nameSelector);
				}
				for (Iterator<FileSet> s = configFileSets.keySet().iterator(); s.hasNext();) {
					FileSet fileset = s.next();
					String finalFolder = configFileSets.get(fileset);
					String[] found = selectFiles(orSelector, finalFolder, fileset.getDirectoryScanner().getIncludedFiles());
					if (found.length > 0)
						advice.addPermissions(config, permissionKey.substring(Utils.ROOT_PERMISSIONS.length()), found);
				}
			}
		}
		return advice;
	}

	/*
	 * Select from the given files those that match the passed in group of OR'ed FilenameSelectors
	 * We can't just use the selectors directly on the fileset because the files may be going to different
	 * folders.  They will end up under the given folder, which is either the root, or the folder corresponding 
	 * to "root.folder" properties. 
	 */
	private String[] selectFiles(OrSelector selector, String folder, String[] files) {
		String prefix = (folder.length() > 0) ? folder + '/' : ""; //$NON-NLS-1$
		ArrayList<String> result = new ArrayList<String>();

		for (int i = 0; i < files.length; i++) {
			String finalLocation = prefix + files[i];
			//FilenameSelector is checking based on File.separatorChar, so normalize
			finalLocation = finalLocation.replace('/', File.separatorChar).replace('\\', File.separatorChar);
			//FilenameSelector objects only care about the filename and not the other arguments
			if (selector.isSelected(null, finalLocation, null))
				result.add(finalLocation.replace('\\', '/')); //we work with '/'
		}
		return result.toArray(new String[result.size()]);
	}

	public void setBuildResultFolder(String buildResultFolder) {
		if (buildResultFolder != null && buildResultFolder.length() > 0 && !buildResultFolder.startsWith(ANT_PREFIX))
			this.buildResultFolder = buildResultFolder;
	}

	public void setTargetFolder(String targetFolder) {
		if (targetFolder != null && targetFolder.length() > 0 && !targetFolder.startsWith(ANT_PREFIX))
			this.targetFolder = targetFolder;
	}

	public void setLicenseDirectory(String licenseDirectory) {
		if (licenseDirectory != null && licenseDirectory.length() > 0 && !licenseDirectory.startsWith(ANT_PREFIX))
			this.licenseDirectory = licenseDirectory;
	}
}
