// ***************************************************************************************************************************
// * 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.cp;

import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.reflect.ReflectFlags.*;

import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.reflect.*;

/**
 * Factory for creating beans.
 */
public class BeanFactory {

	/**
	 * Non-existent bean factory.
	 */
	public static final class Null extends BeanFactory {}

	private final Map<Class<?>,Supplier<?>> beanMap = new ConcurrentHashMap<>();
	private final Optional<BeanFactory> parent;
	private final Optional<Object> outer;

	/**
	 * Static creator.
	 *
	 * @return A new {@link BeanFactory} object.
	 */
	public static BeanFactory create() {
		return new BeanFactory();
	}

	/**
	 * Static creator.
	 *
	 * @param parent Parent bean factory.  Can be <jk>null</jk> if this is the root resource.
	 * @param outer Outer bean context to use when instantiating local classes.  Can be <jk>null</jk>.
	 * @return A new {@link BeanFactory} object.
	 */
	public static BeanFactory of(BeanFactory parent, Object outer) {
		return new BeanFactory(parent, outer);
	}

	/**
	 * Default constructor.
	 */
	public BeanFactory() {
		this(Optional.empty(), Optional.empty());
	}

	/**
	 * Constructor.
	 *
	 * @param parent Parent bean factory.  Can be <jk>null</jk> if this is the root resource.
	 * @param outer Outer bean context to use when instantiating local classes.  Can be <jk>null</jk>.
	 */
	public BeanFactory(BeanFactory parent, Object outer) {
		this(Optional.ofNullable(parent), Optional.ofNullable(outer));
	}

	/**
	 * Constructor.
	 *
	 * @param parent - Optional parent bean factory.
	 * @param outer Outer bean context to use when instantiating local classes.
	 */
	public BeanFactory(Optional<BeanFactory> parent, Optional<Object> outer) {
		this.parent = parent;
		this.outer = outer;
	}

	/**
	 * Returns the bean of the specified type.
	 *
	 * @param <T> The type of bean to return.
	 * @param c The type of bean to return.
	 * @return The bean.
	 */
	@SuppressWarnings("unchecked")
	public <T> Optional<T> getBean(Class<T> c) {
		Supplier<?> o = beanMap.get(c);
		if (o == null && parent.isPresent())
			return parent.get().getBean(c);
		T t = (T)(o == null ? null : o.get());
		return Optional.ofNullable(t);
	}

	/**
	 * Returns the bean of the specified type.
	 *
	 * @param c The type of bean to return.
	 * @return The bean.
	 */
	public Optional<?> getBean(ClassInfo c) {
		return getBean(c.inner());
	}

	/**
	 * Adds a bean of the specified type to this factory.
	 *
	 * @param <T> The class to associate this bean with.
	 * @param c The class to associate this bean with.
	 * @param t The bean.
	 * @return This object (for method chaining).
	 */
	public <T> BeanFactory addBean(Class<T> c, T t) {
		if (t == null)
			beanMap.remove(c);
		else
			beanMap.put(c, ()->t);
		return this;
	}

	/**
	 * Adds a bean supplier of the specified type to this factory.
	 *
	 * @param <T> The class to associate this bean with.
	 * @param c The class to associate this bean with.
	 * @param t The bean supplier.
	 * @return This object (for method chaining).
	 */
	public <T> BeanFactory addBeanSupplier(Class<T> c, Supplier<T> t) {
		if (t == null)
			beanMap.remove(c);
		else
			beanMap.put(c, t);
		return this;
	}

	/**
	 * Returns <jk>true</jk> if this factory contains the specified bean type instance.
	 *
	 * @param c The bean type to check.
	 * @return <jk>true</jk> if this factory contains the specified bean type instance.
	 */
	public boolean hasBean(Class<?> c) {
		return getBean(c).isPresent();
	}

	/**
	 * Returns <jk>true</jk> if this factory contains the specified bean type instance.
	 *
	 * @param c The bean type to check.
	 * @return <jk>true</jk> if this factory contains the specified bean type instance.
	 */
	public final boolean hasBean(ClassInfo c) {
		return hasBean(c.inner());
	}

	/**
	 * Creates a bean of the specified type.
	 *
	 * @param <T> The bean type to create.
	 * @param c The bean type to create.
	 * @return A newly-created bean.
	 * @throws ExecutableException If bean could not be created.
	 */
	public <T> T createBean(Class<T> c) throws ExecutableException {

		Optional<T> o = getBean(c);
		if (o.isPresent())
			return o.get();

		ClassInfo ci = ClassInfo.of(c);

		Supplier<String> msg = null;

		for (MethodInfo m : ci.getPublicMethods()) {
			if (m.isAll(STATIC, NOT_DEPRECATED) && m.hasReturnType(c) && (!m.hasAnnotation(BeanIgnore.class))) {
				String n = m.getSimpleName();
				if (isOneOf(n, "create","getInstance")) {
					List<ClassInfo> missing = getMissingParamTypes(m.getParamTypes());
					if (missing.isEmpty())
						return m.invoke(null, getParams(m.getParamTypes()));
					msg = ()-> "Static creator found but could not find prerequisites: " + missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(","));
				}
			}
		}

		if (ci.isInterface())
			throw new ExecutableException("Could not instantiate class {0}: {1}.", c.getName(), msg != null ? msg.get() : "Class is an interface");
		if (ci.isAbstract())
			throw new ExecutableException("Could not instantiate class {0}: {1}.", c.getName(), msg != null ? msg.get() : "Class is abstract");

		for (ConstructorInfo cc : ci.getPublicConstructors()) {
			List<ClassInfo> missing = getMissingParamTypes(cc.getParamTypes());
			if (missing.isEmpty())
				return cc.invoke(getParams(cc.getParamTypes()));
			msg = ()-> "Public constructor found but could not find prerequisites: " + missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(","));
		}

		if (msg == null)
			msg = () -> "Public constructor or creator not found";

		throw new ExecutableException("Could not instantiate class {0}: {1}.", c.getName(), msg.get());
	}

	/**
	 * Create a method finder for finding bean creation methods.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// The bean we want to create.</jc>
	 * 	<jk>public class</jk> A {}
	 *
	 * 	<jc>// The bean that has a creator method for the bean above.</jc>
	 * 	<jk>public class</jk> B {
	 *
	 * 		<jc>// Creator method.</jc>
	 * 		<jc>// Bean factory must have a C bean and optionally a D bean.</jc>
	 * 		<jk>public</jk> A createA(C <mv>c</mv>, Optional&lt;D&gt; <mv>d</mv>) {
	 * 			<jk>return new</jk> A(<mv>c</mv>, <mv>d</mv>.orElse(<jk>null</jk>));
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Instantiate the bean with the creator method.</jc>
	 * 	B <mv>b</mv> = <jk>new</jk> B();
	 *
	 *  <jc>// Create a bean factory with some mapped beans.</jc>
	 * 	BeanFactory <mv>beanFactory</mv> = BeanFactory.<jsm>create</jsm>().addBean(C.<jk>class</jk>, <jk>new</jk> C());
	 *
	 * 	<jc>// Instantiate the bean using the creator method.</jc>
	 * 	A <mv>a</mv> = <mv>beanFactory</mv>
	 * 		.beanCreateMethodFinder(A.<jk>class</jk>, <mv>b</mv>)  <jc>// Looking for creator for A on b object.</jc>
	 * 		.find(<js>"createA"</js>)                         <jc>// Look for method called "createA".</jc>
	 * 		.thenFind(<js>"createA2"</js>)                    <jc>// Then look for method called "createA2".</jc>
	 * 		.withDefault(()-&gt;<jk>new</jk> A())                        <jc>// Optionally supply a default value if method not found.</jc>
	 * 		.run();                                  <jc>// Execute.</jc>
	 * </p>
	 *
	 * @param <T> The bean type to create.
	 * @param c The bean type to create.
	 * @param resource The class containing the bean creator method.
	 * @return The created bean or the default value if method could not be found.
	 */
	public <T> BeanCreateMethodFinder<T> beanCreateMethodFinder(Class<T> c, Object resource) {
		return new BeanCreateMethodFinder<>(c, resource, this);
	}

	/**
	 * Given the list of param types, returns a list of types that are missing from this factory.
	 *
	 * @param paramTypes The param types to chec.
	 * @return A list of types that are missing from this factory.
	 */
	public List<ClassInfo> getMissingParamTypes(List<ClassInfo> paramTypes) {
		List<ClassInfo> l = AList.create();
		for (int i = 0; i < paramTypes.size(); i++) {
			ClassInfo pt = paramTypes.get(i);
			ClassInfo ptu = pt.unwrap(Optional.class);
			if (i == 0 && ptu.isInstance(outer.orElse(null)))
				continue;
			if (! hasBean(ptu))
				if (! pt.is(Optional.class))
					l.add(pt);
		}
		return l;
	}

	/**
	 * Returns the corresponding beans in this factory for the specified param types.
	 *
	 * @param paramTypes The param types to get from this factory.
	 * @return The corresponding beans in this factory for the specified param types.
	 */
	public Object[] getParams(List<ClassInfo> paramTypes) {
		Object[] o = new Object[paramTypes.size()];
		for (int i = 0; i < paramTypes.size(); i++) {
			ClassInfo pt = paramTypes.get(i);
			ClassInfo ptu = pt.unwrap(Optional.class);
			if (i == 0 && ptu.isInstance(outer.orElse(null)))
				o[i] = outer.get();
			else {
				if (pt.is(Optional.class)) {
					o[i] = getBean(ptu);
				} else {
					o[i] = getBean(ptu).get();
				}
			}
		}
		return o;
	}

	/**
	 * Returns the contents of this bean factory as a readable map of values.
	 *
	 * @return The contents of this bean factory as a readable map of values.
	 */
	public OMap toMap() {
		return OMap.create()
			.a("beanMap", beanMap.keySet().stream().map(x -> x.getSimpleName()).collect(Collectors.toList()))
			.appendSkipNull("outer", ObjectUtils.identity(outer))
			.appendSkipNull("parent", parent.orElse(null));
	}

	@Override /* Object */
	public String toString() {
		return toMap().toString();
	}
}
