/*******************************************************************************
 * Copyright (c) 2007, 2018 IBM Corporation and others.
 * All rights reserved.
 * 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: 
 * 		IBM Corporation - initial API and implementation
 * 		Red Hat, Inc (Krzysztof Daniel) - Bug 421935: Extend simpleconfigurator to
 * read .info files from many locations
 ******************************************************************************/
package org.eclipse.equinox.internal.simpleconfigurator.utils;

import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.util.*;
import org.eclipse.equinox.internal.simpleconfigurator.Activator;
import org.osgi.framework.Version;

public class SimpleConfiguratorUtils {

	private static final String LINK_KEY = "link";
	private static final String LINK_FILE_EXTENSION = ".link";
	private static final String UNC_PREFIX = "//";
	private static final String VERSION_PREFIX = "#version=";
	public static final String ENCODING_UTF8 = "#encoding=UTF-8";
	public static final Version COMPATIBLE_VERSION = new Version(1, 0, 0);

	private static final String FILE_SCHEME = "file";
	private static final String REFERENCE_PREFIX = "reference:";
	private static final String FILE_PREFIX = "file:";
	private static final String COMMA = ",";
	private static final String ENCODED_COMMA = "%2C";

	private static final Set<File> reportedExtensions = Collections.synchronizedSet(new HashSet<File>(0));

	public static List<BundleInfo> readConfiguration(URL url, URI base) throws IOException {
		List<BundleInfo> result = new ArrayList<>();

		//old behaviour
		result.addAll(readConfigurationFromFile(url, base));

		if (!Activator.EXTENDED) {
			return result;
		}
		readExtendedConfigurationFiles(result);
		//dedup - some bundles may be listed more than once
		removeDuplicates(result);
		return result;
	}

	public static void removeDuplicates(List<BundleInfo> result) {
		if (result.size() > 1) {
			int index = 0;
			while (index < result.size()) {
				String aSymbolicName = result.get(index).getSymbolicName();
				String aVersion = result.get(index).getVersion();

				for (int i = index + 1; i < result.size();) {
					String bSymbolicName = result.get(i).getSymbolicName();
					String bVersion = result.get(i).getVersion();
					if (aSymbolicName.equals(bSymbolicName) && aVersion.equals(bVersion)) {
						result.remove(i);
					} else {
						i++;
					}
				}

				index++;
			}
		}
	}

	public static void readExtendedConfigurationFiles(List<BundleInfo> result) throws IOException, FileNotFoundException, MalformedURLException {
		//extended behaviour
		List<File> files;
		try {
			files = getInfoFiles();
			for (File info : files) {
				List<BundleInfo> list = readConfigurationFromFile(info.toURL(), info.getParentFile().toURI());
				// extensions are relative to extension root, not to the framework
				// it is necessary to replace relative locations with absolute ones
				for (int i = 0; i < list.size(); i++) {
					BundleInfo singleInfo = list.get(i);
					if (singleInfo.getBaseLocation() != null) {
						singleInfo = new BundleInfo(singleInfo.getSymbolicName(), singleInfo.getVersion(), singleInfo.getBaseLocation().resolve(singleInfo.getLocation()), singleInfo.getStartLevel(), singleInfo.isMarkedAsStarted());
						list.remove(i);
						list.add(i, singleInfo);
					}
				}
				if (Activator.DEBUG) {
					System.out.println("List of bundles to be loaded from " + info.toURL());
					for (BundleInfo b : list) {
						System.out.println(b.getSymbolicName() + "_" + b.getVersion());
					}
				}
				result.addAll(list);
			}
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException("Couldn't parse simpleconfigurator extensions", e);
		}
	}

	public static ArrayList<File> getInfoFiles() throws IOException, FileNotFoundException, URISyntaxException {
		ArrayList<File> files = new ArrayList<>(1);

		if (Activator.EXTENSIONS != null) {
			//configured simpleconfigurator extensions location
			String stringExtenionLocation = Activator.EXTENSIONS;
			String[] locationToCheck = stringExtenionLocation.split(",");
			for (String location : locationToCheck) {
				files.addAll(getInfoFilesFromLocation(location));
			}
		}
		return files;
	}

	private static ArrayList<File> getInfoFilesFromLocation(String locationToCheck) throws IOException, FileNotFoundException, URISyntaxException {
		ArrayList<File> result = new ArrayList<>(1);

		File extensionsLocation = new File(locationToCheck);

		if (extensionsLocation.exists() && extensionsLocation.isDirectory()) {
			//extension location contains extensions
			File[] extensions = extensionsLocation.listFiles();
			for (File extension : extensions) {
				if (extension.isFile() && extension.getName().endsWith(LINK_FILE_EXTENSION)) {
					Properties link = new Properties();
					link.load(new FileInputStream(extension));
					String newInfoName = link.getProperty(LINK_KEY);
					URI newInfoURI = new URI(newInfoName);
					File newInfoFile = null;
					if (newInfoURI.isAbsolute()) {
						newInfoFile = new File(newInfoName);
					} else {
						newInfoFile = new File(extension.getParentFile(), newInfoName);
					}
					if (newInfoFile.exists()) {
						extension = newInfoFile.getParentFile();
					}
				}

				if (extension.isDirectory()) {
					if (Files.isWritable(extension.toPath())) {
						synchronized (reportedExtensions) {
							if (!reportedExtensions.contains(extension)) {
								reportedExtensions.add(extension);
								System.err.println("Fragment directory should be read only " + extension);
							}
						}
						continue;
					}
					File[] listFiles = extension.listFiles();
					// new magic - multiple info files, f.e.
					//   egit.info (git feature)
					//   cdt.link (properties file containing link=path) to other info file
					for (File file : listFiles) {
						//if it is a info file - load it
						if (file.getName().endsWith(".info")) {
							result.add(file);
						}
						// if it is a link - dereference it
					}
				} else if (Activator.DEBUG) {
					synchronized (reportedExtensions) {
						if (!reportedExtensions.contains(extension)) {
							reportedExtensions.add(extension);
							System.out.println("Unrecognized fragment " + extension);
						}
					}
				}
			}
		}
		return result;
	}

	private static List<BundleInfo> readConfigurationFromFile(URL url, URI base) throws IOException {
		InputStream stream = null;
		try {
			stream = url.openStream();
		} catch (IOException e) {
			// if the exception is a FNF we return an empty bundle list
			if (e instanceof FileNotFoundException)
				return Collections.emptyList();
			throw e;
		}

		try {
			return readConfiguration(stream, base);
		} finally {
			stream.close();
		}
	}

	/**
	 * Read the configuration from the given InputStream
	 * 
	 * @param stream - the stream is always closed 
	 * @param base
	 * @return List of {@link BundleInfo}
	 * @throws IOException
	 */
	public static List<BundleInfo> readConfiguration(InputStream stream, URI base) throws IOException {
		List<BundleInfo> bundles = new ArrayList<>();

		BufferedInputStream bufferedStream = new BufferedInputStream(stream);
		String encoding = determineEncoding(bufferedStream);

		String line;
		try (BufferedReader r = new BufferedReader(encoding == null ? new InputStreamReader(bufferedStream) : new InputStreamReader(bufferedStream, encoding));) {
			while ((line = r.readLine()) != null) {
				line = line.trim();
				//ignore any comment or empty lines
				if (line.length() == 0)
					continue;

				if (line.startsWith("#")) {//$NON-NLS-1$
					parseCommentLine(line);
					continue;
				}

				BundleInfo bundleInfo = parseBundleInfoLine(line, base);
				if (bundleInfo != null)
					bundles.add(bundleInfo);
			}
		}
		return bundles;
	}

	/*
	 * We expect the first line of the bundles.info to be 
	 *    #encoding=UTF-8
	 * if it isn't, then it is an older bundles.info and should be 
	 * read with the default encoding
	 */
	private static String determineEncoding(BufferedInputStream stream) {
		byte[] utfBytes = ENCODING_UTF8.getBytes();
		byte[] buffer = new byte[utfBytes.length];

		int bytesRead = -1;
		stream.mark(utfBytes.length + 1);
		try {
			bytesRead = stream.read(buffer);
		} catch (IOException e) {
			//do nothing
		}

		if (bytesRead == utfBytes.length && Arrays.equals(utfBytes, buffer))
			return "UTF-8";

		//if the first bytes weren't the encoding, need to reset
		try {
			stream.reset();
		} catch (IOException e) {
			// nothing
		}
		return null;
	}

	public static void parseCommentLine(String line) {
		// version
		if (line.startsWith(VERSION_PREFIX)) {
			String version = line.substring(VERSION_PREFIX.length()).trim();
			if (!COMPATIBLE_VERSION.equals(new Version(version)))
				throw new IllegalArgumentException("Invalid version: " + version);
		}
	}

	public static BundleInfo parseBundleInfoLine(String line, URI base) {
		// symbolicName,version,location,startLevel,markedAsStarted
		StringTokenizer tok = new StringTokenizer(line, COMMA);
		int numberOfTokens = tok.countTokens();
		if (numberOfTokens < 5)
			throw new IllegalArgumentException("Line does not contain at least 5 tokens: " + line);

		String symbolicName = tok.nextToken().trim();
		String version = tok.nextToken().trim();
		URI location = parseLocation(tok.nextToken().trim());
		int startLevel = Integer.parseInt(tok.nextToken().trim());
		boolean markedAsStarted = Boolean.parseBoolean(tok.nextToken());
		BundleInfo result = new BundleInfo(symbolicName, version, location, startLevel, markedAsStarted);
		if (!location.isAbsolute())
			result.setBaseLocation(base);
		return result;
	}

	public static URI parseLocation(String location) {
		// decode any commas we previously encoded when writing this line
		int encodedCommaIndex = location.indexOf(ENCODED_COMMA);
		while (encodedCommaIndex != -1) {
			location = location.substring(0, encodedCommaIndex) + COMMA + location.substring(encodedCommaIndex + 3);
			encodedCommaIndex = location.indexOf(ENCODED_COMMA);
		}

		if (File.separatorChar != '/') {
			int colon = location.indexOf(':');
			String scheme = colon < 0 ? null : location.substring(0, colon);
			if (scheme == null || scheme.equals(FILE_SCHEME))
				location = location.replace(File.separatorChar, '/');
			//if the file is a UNC path, insert extra leading // if needed to make a valid URI (see bug 207103)
			if (scheme == null) {
				if (location.startsWith(UNC_PREFIX) && !location.startsWith(UNC_PREFIX, 2))
					location = UNC_PREFIX + location;
			} else {
				//insert UNC prefix after the scheme
				if (location.startsWith(UNC_PREFIX, colon + 1) && !location.startsWith(UNC_PREFIX, colon + 3))
					location = location.substring(0, colon + 3) + location.substring(colon + 1);
			}
		}

		try {
			URI uri = new URI(location);
			if (!uri.isOpaque())
				return uri;
		} catch (URISyntaxException e1) {
			// this will catch the use of invalid URI characters (e.g. spaces, etc.)
			// ignore and fall through
		}

		try {
			return URIUtil.fromString(location);
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException("Invalid location: " + location);
		}
	}

	public static void transferStreams(List<InputStream> sources, OutputStream destination) throws IOException {
		destination = new BufferedOutputStream(destination);
		try {
			for (int i = 0; i < sources.size(); i++) {
				try (InputStream source = new BufferedInputStream(sources.get(i))) {
					byte[] buffer = new byte[8192];
					while (true) {
						int bytesRead = -1;
						if ((bytesRead = source.read(buffer)) == -1)
							break;
						destination.write(buffer, 0, bytesRead);
					}
				}
			}
		} finally {
			try {
				destination.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}

	// This will produce an unencoded URL string
	public static String getBundleLocation(BundleInfo bundle, boolean useReference) {
		URI location = bundle.getLocation();
		String scheme = location.getScheme();
		String host = location.getHost();
		String path = location.getPath();

		if (location.getScheme() == null) {
			URI baseLocation = bundle.getBaseLocation();
			if (baseLocation != null && baseLocation.getScheme() != null) {
				scheme = baseLocation.getScheme();
				host = baseLocation.getHost();
			}
		}

		String bundleLocation = null;
		try {
			URL bundleLocationURL = new URL(scheme, host, path);
			bundleLocation = bundleLocationURL.toExternalForm();

		} catch (MalformedURLException e1) {
			bundleLocation = location.toString();
		}

		if (useReference && bundleLocation.startsWith(FILE_PREFIX))
			bundleLocation = REFERENCE_PREFIX + bundleLocation;
		return bundleLocation;
	}

	public static long getExtendedTimeStamp() {
		long regularTimestamp = -1;
		if (Activator.EXTENDED) {
			try {
				ArrayList<File> infoFiles = SimpleConfiguratorUtils.getInfoFiles();
				for (File f : infoFiles) {
					long infoFileLastModified = getFileLastModified(f);
					// pick latest modified always
					if (infoFileLastModified > regularTimestamp) {
						regularTimestamp = infoFileLastModified;
					}
				}
			} catch (IOException | URISyntaxException e) {
				if (Activator.DEBUG) {
					e.printStackTrace();
				}
			}
			if (Activator.DEBUG) {
				System.out.println("Fragments timestamp: " + regularTimestamp);
			}
		}
		return regularTimestamp;
	}

	public static long getFileLastModified(File file) {
		long lastModified = file.lastModified();
		if (lastModified == 0) {
			try {
				// Note that "ctime" is different to a file's creation time (on posix
				// platforms creation time is a synonym for last modified time)
				FileTime ctime = (FileTime) Files.getAttribute(file.toPath(), "unix:ctime");
				lastModified = ctime.toMillis();
			} catch (UnsupportedOperationException | IllegalArgumentException | IOException e) {
				// We expect this attribute to not exist on non-posix platforms like Windows
			}
		}
		return lastModified;
	}
}
