/*=============================================================================#
 # Copyright (c) 2011, 2020 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.rj.server.util;

import static org.eclipse.statet.rj.server.util.RJContext.RJ_PATH_SEPARATOR;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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.CommonsRuntime;
import org.eclipse.statet.jcommons.runtime.bundle.BundleEntry;
import org.eclipse.statet.jcommons.runtime.bundle.BundleSpec;

import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.server.RjsStatus;


/**
 * Server utilities.
 */
@NonNullByDefault
public class ServerUtils {
	
	
	public static final String JCOMMONS_UTIL_ID= "org.eclipse.statet.jcommons.util"; //$NON-NLS-1$
	public static final BundleSpec JCOMMONS_UTIL_SPEC= new BundleSpec(JCOMMONS_UTIL_ID, CommonsRuntime.class);
	
	public static final String RJ_DATA_ID= "org.eclipse.statet.rj.data"; //$NON-NLS-1$
	public static final BundleSpec RJ_DATA_SPEC= new BundleSpec(RJ_DATA_ID, RObject.class);
	public static final String RJ_SERVER_ID= "org.eclipse.statet.rj.server"; //$NON-NLS-1$
	public static final BundleSpec RJ_SERVER_SPEC= new BundleSpec(RJ_SERVER_ID, RJContext.class);
	
	public static final ImList<BundleSpec> MIN_CLASSPATH_SPECS= ImCollections.newList(
			JCOMMONS_UTIL_SPEC,
			RJ_DATA_SPEC, RJ_SERVER_SPEC );
	
	public static final ImList<BundleSpec> MIN_RMI_CODEBASE_SPECS= ImCollections.newList(
			RJ_SERVER_SPEC );
	
	
	public static final int[] RJ_VERSION= new int[] { 4, 0, 0 };
	
	public static final RjsStatus MISSING_ANSWER_STATUS= new RjsStatus(RjsStatus.ERROR, 121, "Server error (missing answer).");
	
	
	public static class ArgKeyValue {
		
		private final String key;
		private final @Nullable String value;
		
		public ArgKeyValue(final String key, final @Nullable String value) {
			this.key= key;
			this.value= value;
		}
		
		
		public String getKey() {
			return this.key;
		}
		
		public @Nullable String getValue() {
			return this.value;
		}
		
	}
	
	/**
	 * Split at next ':'
	 * @param arg the argument to split
	 * @return key value pair
	 */
	public static ArgKeyValue getArgSubValue(final @Nullable String arg) {
		if (arg != null && arg.length() > 0) {
			final int idx= arg.indexOf(':');
			if (idx >= 0) {
				return new ArgKeyValue(arg.substring(0, idx), arg.substring(idx + 1));
			}
			else {
				return new ArgKeyValue(arg, null);
			}
		}
		else {
			return new ArgKeyValue("", null); //$NON-NLS-1$
		}
	}
	
	/**
	 * Split at next '='
	 * @param arg the argument to split
	 * @return key value pair
	 */
	public static ArgKeyValue getArgConfigValue(final @Nullable String arg) {
		if (arg != null && arg.length() > 0) {
			final int idx= arg.indexOf('=');
			if (idx >= 0) {
				return new ArgKeyValue(arg.substring(0, idx), arg.substring(idx + 1));
			}
			else {
				return new ArgKeyValue(arg, null);
			}
		}
		else {
			return new ArgKeyValue("", null); //$NON-NLS-1$
		}
	}
	
	/**
	 * Split at ','
	 * @param arg the argument to split
	 * @return List with String
	 */
	public static List<String> getArgValueList(final @Nullable String arg) {
		if (arg != null && arg.length() > 0) {
			return Arrays.asList(arg.split(",")); //$NON-NLS-1$
		}
		else {
			return Collections.emptyList();
		}
	}
	
	public static void prettyPrint(final Map map, final StringBuilder sb) {
		final String sep= System.getProperty("line.separator")+"\t";
		final Set<Entry<?, ?>> entrySet= map.entrySet();
		for (final Entry<?, ?> entry : entrySet) {
			sb.append(sep);
			sb.append(entry.getKey());
			sb.append('=');
			final Object value= entry.getValue();
			if (value != null) {
				sb.append(value);
			}
		}
	}
	
	public static void prettyPrint(final Collection<?> list, final StringBuilder sb) {
		final String sep= System.getProperty("line.separator")+"\t";
		for (final Object value : list) {
			sb.append(sep);
			if (value != null) {
				sb.append(value);
			}
		}
	}
	
	public static void prettyPrintVersion(final int[] version, final StringBuilder sb) {
		if (version == null || version.length == 0) {
			sb.append("<missing>");
		}
		else {
			sb.append(version[0]);
			for (int i= 1; i < version.length; i++) {
				sb.append('.');
				sb.append(version[i]);
			}
		}
	}
	
	
	public static String concatJClassPath(final Collection<BundleEntry> entries) {
		if (entries.isEmpty()) {
			return "";
		}
		final List<String> uniqueStrings= new ArrayList<>(entries.size());
		final StringBuilder sb= new StringBuilder();
		for (final BundleEntry entry : entries) {
			final String s= entry.getJClassPathString();
			if (!uniqueStrings.contains(s)) {
				uniqueStrings.add(s);
				sb.append(s);
				sb.append(File.pathSeparatorChar);
			}
		}
		return sb.substring(0, sb.length() - 1);
	}
	
	public static String concatRJClassPath(final Collection<BundleEntry> entries) {
		if (entries.isEmpty()) {
			return "";
		}
		final List<String> uniqueStrings= new ArrayList<>(entries.size());
		final StringBuilder sb= new StringBuilder();
		for (final BundleEntry entry : entries) {
			final String s= entry.getJClassPathUrlString();
			if (!uniqueStrings.contains(s)) {
				uniqueStrings.add(s);
				sb.append(s);
				sb.append(RJ_PATH_SEPARATOR);
			}
		}
		return sb.substring(0, sb.length() - RJ_PATH_SEPARATOR.length());
	}
	
	/**
	 * Concats the specified entries to a valid codebase property value.
	 * The entries have to be path in the local file system. It is recommend to specify the entries
	 * as URL with the schema 'file'.
	 */
	public static String concatCodebase(final Collection<BundleEntry> entries) {
		if (entries.isEmpty()) {
			return "";
		}
		final List<String> uniqueStrings= new ArrayList<>(entries.size());
		final StringBuilder sb= new StringBuilder();
		for (final BundleEntry entry : entries) {
			final String s= entry.getJClassPath().toUri().toString();
			if (s != null && !uniqueStrings.contains(s)) {
				sb.append(s);
				sb.append(' ');
			}
		}
		return sb.substring(0, sb.length()-1);
	}
	
	public static boolean delDir(final File dir) {
		final String[] children= dir.list();
		for (final String child : children) {
			final File file= new File(dir, child);
			if (file.isDirectory()) {
				delDir(file);
			}
			else {
				file.delete();
			}
		}
		return dir.delete();
	}
	
	public static void cleanDir(final File dir, final String exclude) {
		final String[] children= dir.list();
		for (final String child : children) {
			if (child.equals(exclude)) {
				continue;
			}
			final File file= new File(dir, child);
			if (file.isDirectory()) {
				delDir(file);
			}
			else {
				file.delete();
			}
		}
	}
	
}
