// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.utils;

import static org.apache.juneau.internal.StringUtils.*;
import static java.lang.Character.*;

import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.*;

/**
 * Allows arbitrary objects to be mapped to classes and methods base on class/method name keys.
 *
 * <p>
 * The valid pattern matches are:
 * <ul class='spaced-list'>
 *  <li>Classes:
 * 		<ul>
 * 			<li>Fully qualified:
 * 				<ul>
 * 					<li><js>"com.foo.MyClass"</js>
 * 				</ul>
 * 			<li>Fully qualified inner class:
 * 				<ul>
 * 					<li><js>"com.foo.MyClass$Inner1$Inner2"</js>
 * 				</ul>
 * 			<li>Simple:
 * 				<ul>
 * 					<li><js>"MyClass"</js>
 * 				</ul>
 * 			<li>Simple inner:
 * 				<ul>
 * 					<li><js>"MyClass$Inner1$Inner2"</js>
 * 					<li><js>"Inner1$Inner2"</js>
 * 					<li><js>"Inner2"</js>
 * 				</ul>
 * 		</ul>
 * 	<li>Methods:
 * 		<ul>
 * 			<li>Fully qualified with args:
 * 				<ul>
 * 					<li><js>"com.foo.MyClass.myMethod(String,int)"</js>
 * 					<li><js>"com.foo.MyClass.myMethod(java.lang.String,int)"</js>
 * 					<li><js>"com.foo.MyClass.myMethod()"</js>
 * 				</ul>
 * 			<li>Fully qualified:
 * 				<ul>
 * 					<li><js>"com.foo.MyClass.myMethod"</js>
 * 				</ul>
 * 			<li>Simple with args:
 * 				<ul>
 * 					<li><js>"MyClass.myMethod(String,int)"</js>
 * 					<li><js>"MyClass.myMethod(java.lang.String,int)"</js>
 * 					<li><js>"MyClass.myMethod()"</js>
 * 				</ul>
 * 			<li>Simple:
 * 				<ul>
 * 					<li><js>"MyClass.myMethod"</js>
 * 				</ul>
 * 			<li>Simple inner class:
 * 				<ul>
 * 					<li><js>"MyClass$Inner1$Inner2.myMethod"</js>
 * 					<li><js>"Inner1$Inner2.myMethod"</js>
 * 					<li><js>"Inner2.myMethod"</js>
 * 				</ul>
 * 		</ul>
 * 	<li>Fields:
 * 		<ul>
 * 			<li>Fully qualified:
 * 				<ul>
 * 					<li><js>"com.foo.MyClass.myField"</js>
 * 				</ul>
 * 			<li>Simple:
 * 				<ul>
 * 					<li><js>"MyClass.myField"</js>
 * 				</ul>
 * 			<li>Simple inner class:
 * 				<ul>
 * 					<li><js>"MyClass$Inner1$Inner2.myField"</js>
 * 					<li><js>"Inner1$Inner2.myField"</js>
 * 					<li><js>"Inner2.myField"</js>
 * 				</ul>
 * 		</ul>
 * 	<li>Constructors:
 * 		<ul>
 * 			<li>Fully qualified with args:
 * 				<ul>
 * 					<li><js>"com.foo.MyClass(String,int)"</js>
 * 					<li><js>"com.foo.MyClass(java.lang.String,int)"</js>
 * 					<li><js>"com.foo.MyClass()"</js>
 * 				</ul>
 * 			<li>Simple with args:
 * 				<ul>
 * 					<li><js>"MyClass(String,int)"</js>
 * 					<li><js>"MyClass(java.lang.String,int)"</js>
 * 					<li><js>"MyClass()"</js>
 * 				</ul>
 * 			<li>Simple inner class:
 * 				<ul>
 * 					<li><js>"MyClass$Inner1$Inner2()"</js>
 * 					<li><js>"Inner1$Inner2()"</js>
 * 					<li><js>"Inner2()"</js>
 * 				</ul>
 * 		</ul>
 * 	<li>A comma-delimited list of anything on this list.
 * </ul>
 *
 * @param <V> The type of object in this map.
 */
public class ReflectionMap<V> {

	private final List<ClassEntry<V>> classEntries;
	private final List<MethodEntry<V>> methodEntries;
	private final List<FieldEntry<V>> fieldEntries;
	private final List<ConstructorEntry<V>> constructorEntries;
	final boolean noClassEntries, noMethodEntries, noFieldEntries, noConstructorEntries;

	/**
	 * Constructor.
	 *
	 * @param b Initializer object.
	 */
	ReflectionMap(Builder<V> b) {
		this.classEntries = Collections.unmodifiableList(new ArrayList<>(b.classEntries));
		this.methodEntries = Collections.unmodifiableList(new ArrayList<>(b.methodEntries));
		this.fieldEntries = Collections.unmodifiableList(new ArrayList<>(b.fieldEntries));
		this.constructorEntries = Collections.unmodifiableList(new ArrayList<>(b.constructorEntries));
		this.noClassEntries = classEntries.isEmpty();
		this.noMethodEntries = methodEntries.isEmpty();
		this.noFieldEntries = fieldEntries.isEmpty();
		this.noConstructorEntries = constructorEntries.isEmpty();
	}

	/**
	 * Static builder creator.
	 *
	 * @param <V> The type of object in this map.
	 * @param c The type of object in this map.
	 * @return A new instance of this object.
	 */
	public static <V> ReflectionMap.Builder<V> create(Class<V> c) {
		return new ReflectionMap.Builder<>();
	}

	/**
	 * Creates a new builder object for {@link ReflectionMap} objects.
	 *
	 * @param <V> The type of object in this map.
	 */
	public static class Builder<V> {
		List<ClassEntry<V>> classEntries = new ArrayList<>();
		List<MethodEntry<V>> methodEntries = new ArrayList<>();
		List<FieldEntry<V>> fieldEntries = new ArrayList<>();
		List<ConstructorEntry<V>> constructorEntries = new ArrayList<>();

		/**
		 * Adds a mapping to this builder.
		 *
		 * @param key
		 * 	The mapping key.
		 * 	<br>Can be any of the following:
		 * 	<ul>
		 * 		<li>Full class name (e.g. <js>"com.foo.MyClass"</js>).
		 * 		<li>Simple class name (e.g. <js>"MyClass"</js>).
		 * 		<li>Full method name (e.g. <js>"com.foo.MyClass.myMethod"</js>).
		 * 		<li>Simple method name (e.g. <js>"MyClass.myMethod"</js>).
		 * 		<li>A comma-delimited list of anything on this list.
		 * 	</ul>
		 * @param value The value for this mapping.
		 * @return This object (for method chaining).
		 */
		public Builder<V> append(String key, V value) {
			if (isEmpty(key))
				throw new RuntimeException("Invalid reflection signature: [" + key + "]");
			try {
				for (String k : splitNames(key)) {
					if (k.endsWith(")")) {
						int i = k.substring(0, k.indexOf('(')).lastIndexOf('.');
						if (i == -1 || isUpperCase(k.charAt(i+1))) {
							constructorEntries.add(new ConstructorEntry<>(k, value));
						} else {
							methodEntries.add(new MethodEntry<>(k, value));
						}
					} else {
						int i = k.lastIndexOf('.');
						if (i == -1) {
							classEntries.add(new ClassEntry<>(k, value));
						} else if (isUpperCase(k.charAt(i+1))) {
							classEntries.add(new ClassEntry<>(k, value));
							fieldEntries.add(new FieldEntry<>(k, value));
						} else {
							methodEntries.add(new MethodEntry<>(k, value));
							fieldEntries.add(new FieldEntry<>(k, value));
						}
					}
				}
			} catch (IndexOutOfBoundsException e) {
				throw new RuntimeException("Invalid reflection signature: [" + key + "]");
			}

			return this;
		}

		/**
		 * Create new instance of {@link ReflectionMap} based on the contents of this builder.
		 *
		 * @return A new {@link ReflectionMap} object.
		 */
		public ReflectionMap<V> build() {
			return new ReflectionMap<>(this);
		}
	}

	static List<String> splitNames(String key) {
		if (key.indexOf(',') == -1)
			return Collections.singletonList(key.trim());
		List<String> l = new ArrayList<>();

		int m = 0;
		boolean escaped = false;
		for (int i = 0; i < key.length(); i++) {
			char c = key.charAt(i);
			if (c == '(')
				escaped = true;
			else if (c == ')')
				escaped = false;
			else if (c == ',' && ! escaped) {
				l.add(key.substring(m, i).trim());
				m = i+1;
			}
		}
		l.add(key.substring(m).trim());

		return l;
	}

	/**
	 * Finds first value in this map that matches the specified class.
	 *
	 * @param c The class to test for.
	 * @param ofType Only return objects of the specified type.
	 * @return The matching object.  Never <jk>null</jk>.
	 */
	public Optional<V> find(Class<?> c, Class<? extends V> ofType) {
		if (! noClassEntries)
			for (ClassEntry<V> e : classEntries)
				if (e.matches(c))
					if (ofType == null || ofType.isInstance(e.value))
						return Optional.of(e.value);
		return Optional.empty();
	}

	/**
	 * Finds first value in this map that matches the specified method.
	 *
	 * @param m The method to test for.
	 * @param ofType Only return objects of the specified type.
	 * @return The matching object.  Never <jk>null</jk>.
	 */
	public Optional<V> find(Method m, Class<? extends V> ofType) {
		if (! noMethodEntries)
			for (MethodEntry<V> e : methodEntries)
				if (e.matches(m))
					if (ofType == null || ofType.isInstance(e.value))
						return Optional.of(e.value);
		return Optional.empty();
	}

	/**
	 * Finds first value in this map that matches the specified field.
	 *
	 * @param f The field to test for.
	 * @param ofType Only return objects of the specified type.
	 * @return The matching object.  Never <jk>null</jk>.
	 */
	public Optional<V> find(Field f, Class<? extends V> ofType) {
		if (! noFieldEntries)
			for (FieldEntry<V> e : fieldEntries)
				if (e.matches(f))
					if (ofType == null || ofType.isInstance(e.value))
						return Optional.of(e.value);
		return Optional.empty();
	}

	/**
	 * Finds first value in this map that matches the specified constructor.
	 *
	 * @param c The constructor to test for.
	 * @param ofType Only return objects of the specified type.
	 * @return The matching object.  Never <jk>null</jk>.
	 */
	public Optional<V> find(Constructor<?> c, Class<? extends V> ofType) {
		if (! noConstructorEntries)
			for (ConstructorEntry<V> e : constructorEntries)
				if (e.matches(c))
					if (ofType == null || ofType.isInstance(e.value))
						return Optional.of(e.value);
		return Optional.empty();
	}

	static class ClassEntry<V> {
		final String simpleName, fullName;
		final V value;

		ClassEntry(String name, V value) {
			this.simpleName = simpleClassName(name);
			this.fullName = name;
			this.value = value;
		}

		public boolean matches(Class<?> c) {
			if (c == null)
				return false;
			return classMatches(simpleName, fullName, c);
		}

		public ObjectMap asMap() {
			return new ObjectMap()
				.append("simpleName", simpleName)
				.append("fullName", fullName)
				.append("value", value);
		}

		@Override
		public String toString() {
			return asMap().toString();
		}
	}

	static class MethodEntry<V> {
		String simpleClassName, fullClassName, methodName, args[];
		V value;

		MethodEntry(String name, V value) {
			int i = name.indexOf('(');
			this.args = i == -1 ? null : split(name.substring(i+1, name.length()-1));
			name = i == -1 ? name : name.substring(0, i);
			i = name.lastIndexOf('.');
			String s1 = name.substring(0, i).trim(), s2 = name.substring(i+1).trim();
			this.simpleClassName = simpleClassName(s1);
			this.fullClassName = s1;
			this.methodName = s2;
			this.value = value;
		}

		public boolean matches(Method m) {
			if (m == null)
				return false;
			Class<?> c = m.getDeclaringClass();
			return
				classMatches(simpleClassName, fullClassName, c)
				&& (isEquals(m.getName(), methodName))
				&& (argsMatch(args, m.getParameterTypes()));
		}

		public ObjectMap asMap() {
			return new ObjectMap()
				.append("simpleClassName", simpleClassName)
				.append("fullClassName", fullClassName)
				.append("methodName", methodName)
				.append("args", args)
				.append("value", value);
		}

		@Override
		public String toString() {
			return asMap().toString();
		}
	}

	static class ConstructorEntry<V> {
		String simpleClassName, fullClassName, args[];
		V value;

		ConstructorEntry(String name, V value) {
			int i = name.indexOf('(');
			this.args = split(name.substring(i+1, name.length()-1));
			name = name.substring(0, i).trim();
			this.simpleClassName = simpleClassName(name);
			this.fullClassName = name;
			this.value = value;
		}

		public boolean matches(Constructor<?> m) {
			if (m == null)
				return false;
			Class<?> c = m.getDeclaringClass();
			return
				classMatches(simpleClassName, fullClassName, c)
				&& (argsMatch(args, m.getParameterTypes()));
		}

		public ObjectMap asMap() {
			return new ObjectMap()
				.append("simpleClassName", simpleClassName)
				.append("fullClassName", fullClassName)
				.append("args", args)
				.append("value", value);
		}

		@Override
		public String toString() {
			return asMap().toString();
		}
	}

	static class FieldEntry<V> {
		String simpleClassName, fullClassName, fieldName;
		V value;

		FieldEntry(String name, V value) {
			int i = name.lastIndexOf('.');
			String s1 = name.substring(0, i), s2 = name.substring(i+1);
			this.simpleClassName = simpleClassName(s1);
			this.fullClassName = s1;
			this.fieldName = s2;
			this.value = value;
		}

		public boolean matches(Field f) {
			if (f == null)
				return false;
			Class<?> c = f.getDeclaringClass();
			return
				classMatches(simpleClassName, fullClassName, c)
				&& (isEquals(f.getName(), fieldName));
		}

		public ObjectMap asMap() {
			return new ObjectMap()
				.append("simpleClassName", simpleClassName)
				.append("fullClassName", fullClassName)
				.append("fieldName", fieldName)
				.append("value", value);
		}

		@Override
		public String toString() {
			return asMap().toString();
		}
	}

	static boolean argsMatch(String[] names, Class<?>[] args) {
		if (names == null)
			return true;
		if (names.length != args.length)
			return false;
		for (int i = 0; i < args.length; i++) {
			String n = names[i];
			Class<?> a = args[i];
			if (! (isEquals(n, a.getSimpleName()) || isEquals(n, a.getName())))
				return false;
		}
		return true;
	}

	static String simpleClassName(String name) {
		int i = name.indexOf('.');
		if (i == -1)
			return name;
		return null;
	}

	static boolean classMatches(String simpleName, String fullName, Class<?> c) {
		// For class org.apache.juneau.a.rttests.RountTripBeansWithBuilders$Ac$Builder
		// c.getSimpleName() == "Builder"
		// c.getFullName() == "org.apache.juneau.a.rttests.RountTripBeansWithBuilders$Ac$Builder"
		// c.getPackage() == "org.apache.juneau.a.rttests"
		String cSimple = c.getSimpleName(), cFull = c.getName();
		if (isEquals(simpleName, cSimple) || isEquals(fullName, cFull))
			return true;
		if (cFull.indexOf('$') != -1) {
			Package p = c.getPackage();
			if (p != null)
				cFull = cFull.substring(p.getName().length() + 1);
			if (isEquals(simpleName, cFull))
				return true;
			int i = cFull.indexOf('$');
			while (i != -1) {
				cFull = cFull.substring(i+1);
				if (isEquals(simpleName, cFull))
					return true;
				i = cFull.indexOf('$');
			}
		}
		return false;
	}

	@Override /* Object */
	public String toString() {
		return new ObjectMap()
			.append("classEntries", classEntries)
			.append("methodEntries", methodEntries)
			.append("fieldEntries", fieldEntries)
			.append("constructorEntries", constructorEntries)
			.toString();
	}
}
