/*=============================================================================#
 # Copyright (c) 2018, 2021 Stephan Wahlbrink 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, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.jcommons.runtime.bundle;

import static org.eclipse.statet.internal.jcommons.runtime.CommonsRuntimeInternals.BUNDLE_ID;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import static org.eclipse.statet.jcommons.runtime.CommonsRuntime.log;

import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.runtime.ClassLoaderUtils;
import org.eclipse.statet.jcommons.runtime.UriUtils;
import org.eclipse.statet.jcommons.runtime.bundle.BundleEntryProvider.DevBinPathEntryProvider;
import org.eclipse.statet.jcommons.runtime.bundle.BundleEntryProvider.JarFilePathEntryProvider;
import org.eclipse.statet.jcommons.status.ErrorStatus;
import org.eclipse.statet.jcommons.status.StatusException;


@NonNullByDefault
public class Bundles {
	
	
	public static final String BUNDLE_RESOLVERS_PROPERTY_KEY= "org.eclipse.statet.jcommons.runtime.bundle.BundleResolvers"; //$NON-NLS-1$
	
	
	private static final Pattern REF_CLASS_JAR_PATTERN= Pattern.compile(
			Pattern.quote(BUNDLE_ID + "/target/" + BUNDLE_ID) + "[^/!]+.jar(?:[!]|$)" ); //$NON-NLS-1$
	
	/**
	 * Creates a bundle resolver.
	 * 
	 * <ol>
	 *   <li>Bundle resolver specified by system property {@link #BUNDLE_RESOLVERS_PROPERTY_KEY}.</li>
	 *   <li>Bundle resolver determined automatically.</li>
	 * </ol>
	 * 
	 * @return a bundle resolver
	 */
	public static BundleResolver createResolver() throws StatusException {
		String id= System.getProperty(BUNDLE_RESOLVERS_PROPERTY_KEY);
		if (id == null || id.isEmpty()) {
			final BundleEntry bundleEntry= detectEntry(Bundles.class);
			if (bundleEntry instanceof BundleEntry.Jar
					&& !REF_CLASS_JAR_PATTERN.matcher(bundleEntry.getUrlString()).find()) {
				id= DefaultBundleResolver.ID;
			}
			else {
				id= RefClassBundleResolver.ID;
			}
		}
		return createResolver(id);
	}
	
	static BundleResolver createResolver(final String id) throws StatusException {
		if (id.equals(DefaultBundleResolver.ID)) {
			return new DefaultBundleResolver(
					detectEntryProvider(Bundles.class) );
		}
		if (id.equals(RefClassBundleResolver.ID)) {
			return new RefClassBundleResolver();
		}
		if (id.indexOf('.') > 0) {
			try {
				final Class<?> resolverClass= Class.forName(id);
				return (BundleResolver)resolverClass.newInstance();
			}
			catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
				throw new StatusException(new ErrorStatus(BUNDLE_ID,
						String.format("Failed to create bundle resolver '%1$s'.", id),
						e ));
			}
		}
		throw new StatusException(new ErrorStatus(BUNDLE_ID,
				String.format("Unknown bundle resolver '%1$s'.", id) ));
	}
	
	
	private static final String FILE_PROTOCOL_REGEX= "\\Qfile:/\\E"; //$NON-NLS-1$
	private static final String JAR_FILE_PROTOCOL_REGEX= "\\Qjar:file:/\\E"; //$NON-NLS-1$
	private static final String BUNDLE_ID_REGEX= "[a-z]+(?:\\.?[a-z]+)*"; //$NON-NLS-1$
	private static final String VER_1_REGEX= "\\_\\d+\\.\\d+[^!/]+"; //$NON-NLS-1$
	private static final String VER_2_REGEX= "\\-\\d+\\.\\d+[^!/]+"; //$NON-NLS-1$
	private static final String JAR_REGEX= "(?<![-._]sources?)\\Q.jar\\E"; //$NON-NLS-1$
	private static final String AUTODETECT_REGEX=
			"(?:" + //$NON-NLS-1$
				"(" + FILE_PROTOCOL_REGEX + ".*)/(" + BUNDLE_ID_REGEX + ")\\Q/target/classes/\\E" + // match 1= file: .. //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			"|" + //$NON-NLS-1$
				"(" + JAR_FILE_PROTOCOL_REGEX + ".*)/(" + BUNDLE_ID_REGEX + // match 2= jar:file: .. //$NON-NLS-1$ //$NON-NLS-2$
						"(?:(" + VER_1_REGEX + ")|(" + VER_2_REGEX + "))?" + // match 3= ver_1, match 4= ver_2 //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						JAR_REGEX + ")\\Q!/\\E" + //$NON-NLS-1$
			")"; //$NON-NLS-1$
	
	private static final Pattern AUTODETECT_PATTERN= Pattern.compile(AUTODETECT_REGEX);
	private static final int AUTODETECT_FILE_PROTOCOL_BASE_NUM= 1;
	private static final int AUTODETECT_FILE_PROTOCOL_NAME_NUM= 2;
	private static final int AUTODETECT_JAR_FILE_PROTOCOL_BASE_NUM= 3;
	private static final int AUTODETECT_JAR_FILE_PROTOCOL_NAME_NUM= 4;
	private static final int AUTODETECT_JAR_FILE_PROTOCOL_VER_1_NUM= 5;
	private static final int AUTODETECT_JAR_FILE_PROTOCOL_VER_2_NUM= 6;
	private static final Pattern JAR_VER_0_PATTERN= Pattern.compile("(.+?)" + JAR_REGEX); //$NON-NLS-1$
	private static final Pattern JAR_VER_1_PATTERN= Pattern.compile("(.+?)" + VER_1_REGEX + JAR_REGEX); //$NON-NLS-1$
	private static final Pattern JAR_VER_2_PATTERN= Pattern.compile("(.+?)" + VER_2_REGEX + JAR_REGEX); //$NON-NLS-1$
	
	
	public static BundleEntryProvider detectEntryProvider(final Class<?> refClass,
			final @Nullable List<Path> expliciteBaseDirectories) throws StatusException {
		String refUrl= null;
		try {
			refUrl= ClassLoaderUtils.getClassLocationUrlString(refClass);
			return detectEntryProvider(refUrl, expliciteBaseDirectories);
		}
		catch (final Exception e) {
			throw new StatusException(new ErrorStatus(BUNDLE_ID,
					String.format("Failed to autodetect bundle location" +
							"\n\tclass= %1$s" + //$NON-NLS-1$
							"\n\turl= %2$s", //$NON-NLS-1$
							(refClass != null) ? refClass.getName() : "<NA>", //$NON-NLS-1$
							(refUrl != null) ? '\'' + refUrl + '\'' : "<NA>" ), //$NON-NLS-1$
					e ));
		}
	}
	
	public static BundleEntryProvider detectEntryProvider(final Class<?> refClass)
			throws StatusException {
		return detectEntryProvider(refClass, null);
	}
	
	public static BundleEntryProvider detectEntryProvider(final String refUrl)
			throws StatusException {
		try {
			return detectEntryProvider(refUrl, null);
		}
		catch (final Exception e) {
			throw new StatusException(new ErrorStatus(BUNDLE_ID,
					String.format("Failed to autodetect bundle location" +
							"\n\turl= %1$s", //$NON-NLS-1$
							(refUrl != null) ? '\'' + refUrl + '\'' : "<NA>" ), //$NON-NLS-1$
					e ));
		}
	}
	
	public static BundleEntry detectEntry(final Class<?> refClass) throws StatusException {
		String refUrl= null;
		try {
			refUrl= ClassLoaderUtils.getClassLocationUrlString(refClass);
			return detectEntry(refUrl);
		}
		catch (final Exception e) {
			throw new StatusException(new ErrorStatus(BUNDLE_ID,
					String.format("Failed to autodetect bundle location" +
							"\n\tclass= %1$s" + //$NON-NLS-1$
							"\n\turl= %2$s", //$NON-NLS-1$
							(refClass != null) ? refClass.getName() : "<NA>", //$NON-NLS-1$
							(refUrl != null) ? '\'' + refUrl + '\'' : "<NA>" ), //$NON-NLS-1$
					e ));
		}
	}
	
	static BundleEntryProvider detectEntryProvider(final String refUrl,
			final @Nullable List<Path> expliciteBaseDirectories) throws Exception {
		List<Closeable> closeables= ImCollections.emptyList();
		try {
			final Matcher matcher= AUTODETECT_PATTERN.matcher(refUrl);
			if (matcher.matches()) {
				int detectedType;
				final URI detectedBaseUri;
				if (matcher.start(AUTODETECT_FILE_PROTOCOL_BASE_NUM) != -1) { // file:
					detectedType= 1;
					final String s= nonNullAssert(matcher.group(AUTODETECT_FILE_PROTOCOL_BASE_NUM));
					detectedBaseUri= new URI(s);
				}
				else if (matcher.start(AUTODETECT_JAR_FILE_PROTOCOL_BASE_NUM) != -1) { // jar:file:
					detectedType= 2;
					final String s= nonNullAssert(matcher.group(AUTODETECT_JAR_FILE_PROTOCOL_BASE_NUM));
					if (s.indexOf(UriUtils.JAR_SEPARATOR) == -1) {
						detectedBaseUri= new URI(s.substring(4)); // remove jar
					}
					else {
						detectedBaseUri= new URI(s);
					}
				}
				else {
					throw new IllegalStateException();
				}
				
				final ImList<Path> baseDirectories;
				{	final Path detectedBaseDirectory= getPath(detectedBaseUri);
					
					final List<Path> uniqueList= new ArrayList<>();
					if (expliciteBaseDirectories != null && !expliciteBaseDirectories.isEmpty()) {
						for (Path baseDirectory : expliciteBaseDirectories) {
							baseDirectory= baseDirectory.normalize();
							if (!uniqueList.contains(baseDirectory)) {
								uniqueList.add(baseDirectory);
							}
						}
					}
					if (!uniqueList.contains(detectedBaseDirectory)) {
						uniqueList.add(detectedBaseDirectory);
					}
					baseDirectories= ImCollections.toList(uniqueList);
				}
				
				final BundleEntryProvider provider;
				if (detectedType == 1) {
					provider= new DevBinPathEntryProvider(baseDirectories,
							closeables );
				}
				else {
					final Pattern fileNamePattern;
					if (matcher.start(AUTODETECT_JAR_FILE_PROTOCOL_VER_1_NUM) != -1) {
						fileNamePattern= JAR_VER_1_PATTERN;
					}
					else if (matcher.start(AUTODETECT_JAR_FILE_PROTOCOL_VER_2_NUM) != -1) {
						fileNamePattern= JAR_VER_2_PATTERN;
					}
					else {
						fileNamePattern= JAR_VER_0_PATTERN;
					}
					provider= new JarFilePathEntryProvider(baseDirectories, fileNamePattern,
							closeables );
				}
				closeables= null;
				
				return provider;
			}
			throw new UnsupportedOperationException("url= " + refUrl); //$NON-NLS-1$
		}
		finally {
			if (closeables != null) {
				close(closeables);
			}
		}
	}
	
	static BundleEntry detectEntry(final String refUrl) throws Exception {
		List<Closeable> closeables= ImCollections.emptyList();
		try {
			final Matcher matcher= AUTODETECT_PATTERN.matcher(refUrl);
			if (matcher.matches()) {
				int detectedType;
				final URI detectedBaseUri;
				final String fileName;
				if (matcher.start(AUTODETECT_FILE_PROTOCOL_BASE_NUM) != -1) { // file:
					detectedType= 1;
					final String s= nonNullAssert(matcher.group(AUTODETECT_FILE_PROTOCOL_BASE_NUM));
					detectedBaseUri= new URI(s);
					fileName= nonNullAssert(matcher.group(AUTODETECT_FILE_PROTOCOL_NAME_NUM));
				}
				else if (matcher.start(AUTODETECT_JAR_FILE_PROTOCOL_BASE_NUM) != -1) { // jar:file:
					detectedType= 2;
					final String s= nonNullAssert(matcher.group(AUTODETECT_JAR_FILE_PROTOCOL_BASE_NUM));
					if (s.indexOf(UriUtils.JAR_SEPARATOR) == -1) {
						detectedBaseUri= new URI(s.substring(4)); // remove jar
					}
					else {
						detectedBaseUri= new URI(s);
					}
					fileName= nonNullAssert(matcher.group(AUTODETECT_JAR_FILE_PROTOCOL_NAME_NUM));
				}
				else {
					throw new IllegalStateException();
				}
				
				final ImList<Path> baseDirectories;
				{	final Path detectedBaseDirectory= getPath(detectedBaseUri);
					
					baseDirectories= ImCollections.newList(detectedBaseDirectory);
				}
				
				final BundleEntryProvider provider;
				if (detectedType == 1) {
					provider= new DevBinPathEntryProvider(baseDirectories,
							closeables );
				}
				else {
					final Pattern fileNamePattern;
					if (matcher.start(AUTODETECT_JAR_FILE_PROTOCOL_VER_1_NUM) != -1) {
						fileNamePattern= JAR_VER_1_PATTERN;
					}
					else if (matcher.start(AUTODETECT_JAR_FILE_PROTOCOL_VER_2_NUM) != -1) {
						fileNamePattern= JAR_VER_2_PATTERN;
					}
					else {
						fileNamePattern= JAR_VER_0_PATTERN;
					}
					provider= new JarFilePathEntryProvider(baseDirectories, fileNamePattern,
							closeables );
				}
				closeables= null;
				return nonNullAssert(
						provider.createEntry(baseDirectories.get(0).resolve(fileName)) );
			}
			throw new UnsupportedOperationException("url= " + refUrl); //$NON-NLS-1$
		}
		finally {
			if (closeables != null) {
				close(closeables);
			}
		}
	}
	
	/**
	 * Enhanced Path.get supporting jar files.
	 */
	static Path getPath(final URI url) throws IOException {
		FileSystem fs= null;
		while (true) {
			try {
				final Path path= Paths.get(url);
				return path.normalize();
			}
			catch (final FileSystemNotFoundException e) {
				final Map<String, String> fsEnv= new HashMap<>();
//				fsEnv.put("create", "true"); //$NON-NLS-1$ //$NON-NLS-2$
				try {
					fs= FileSystems.newFileSystem(url, fsEnv);
//					closeables= ImCollections.newList(fs);
				}
				catch (final FileSystemAlreadyExistsException exists) {}
			}
		}
	}
	
	static void close(final List<Closeable> closeables) {
		for (final Closeable closeable : closeables) {
			try {
				closeable.close();
			}
			catch (final Exception e) {
				log(new ErrorStatus(BUNDLE_ID,
						"An error occurred when disposing closable of path entry provider.",
						e ));
			}
		}
	}
	
	
	private Bundles() {
	}
	
}
