// ***************************************************************************************************************************
// * 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;

import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.util.*;

import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.transform.*;
import org.apache.juneau.xml.annotation.*;

/**
 * Java bean wrapper class.
 *
 * <h5 class='topic'>Description</h5>
 *
 * A wrapper that wraps Java bean instances inside of a {@link Map} interface that allows properties on the wrapped
 * object can be accessed using the {@link Map#get(Object) get()} and {@link Map#put(Object,Object) put()} methods.
 *
 * <p>
 * Use the {@link BeanContext} class to create instances of this class.
 *
 * <h5 class='topic'>Bean property order</h5>
 *
 * The order of the properties returned by the {@link Map#keySet() keySet()} and {@link Map#entrySet() entrySet()}
 * methods are as follows:
 * <ul class='spaced-list'>
 * 	<li>
 * 		If {@link Bean @Bean} annotation is specified on class, then the order is the same as the list of properties
 * 		in the annotation.
 * 	<li>
 * 		If {@link Bean @Bean} annotation is not specified on the class, then the order is the same as that returned
 * 		by the {@link java.beans.BeanInfo} class (i.e. ordered by definition in the class).
 * </ul>
 *
 * <p>
 * <br>The order can also be overridden through the use of a {@link BeanFilter}.
 *
 * <h5 class='topic'>POJO swaps</h5>
 *
 * If {@link PojoSwap PojoSwaps} are defined on the class types of the properties of this bean or the bean properties
 * themselves, the {@link #get(Object)} and {@link #put(String, Object)} methods will automatically transform the
 * property value to and from the serialized form.
 *
 * @param <T> Specifies the type of object that this map encapsulates.
 */
public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T> {

	/** The wrapped object. */
	protected T bean;

	/** Temporary holding cache for beans with read-only properties.  Normally null. */
	protected Map<String,Object> propertyCache;

	/** Temporary holding cache for bean properties of array types when the add() method is being used. */
	protected Map<String,List<?>> arrayPropertyCache;

	/** The BeanMeta associated with the class of the object. */
	protected BeanMeta<T> meta;

	private final BeanSession session;
	private final String beanTypePropertyName;

	/**
	 * Convenience method for wrapping a bean inside a {@link BeanMap}.
	 *
	 * @param <T> The bean type.
	 * @param bean The bean being wrapped.
	 * @return A new {@link BeanMap} instance wrapping the bean.
	 */
	public static <T> BeanMap<T> create(T bean) {
		return BeanContext.DEFAULT.createBeanSession().toBeanMap(bean);
	}

	/**
	 * Instance of this class are instantiated through the BeanContext class.
	 *
	 * @param session The bean session object that created this bean map.
	 * @param bean The bean to wrap inside this map.
	 * @param meta The metadata associated with the bean class.
	 */
	protected BeanMap(BeanSession session, T bean, BeanMeta<T> meta) {
		this.session = session;
		this.bean = bean;
		this.meta = meta;
		if (meta.constructorArgs.length > 0)
			propertyCache = new TreeMap<>();
		this.beanTypePropertyName = session.getBeanTypePropertyName(meta.classMeta);
	}

	/**
	 * Returns the metadata associated with this bean map.
	 *
	 * @return The metadata associated with this bean map.
	 */
	public BeanMeta<T> getMeta() {
		return meta;
	}

	/**
	 * Returns the bean session that created this bean map.
	 *
	 * @return The bean session that created this bean map.
	 */
	public final BeanSession getBeanSession() {
		return session;
	}

	/**
	 * Returns the wrapped bean object.
	 *
	 * <p>
	 * Triggers bean creation if bean has read-only properties set through a constructor defined by the
	 * {@link BeanConstructor @BeanConstructor} annotation.
	 *
	 * @return The inner bean object.
	 */
	public T getBean() {
		T b = getBean(true);

		// If we have any arrays that need to be constructed, do it now.
		if (arrayPropertyCache != null) {
			for (Map.Entry<String,List<?>> e : arrayPropertyCache.entrySet()) {
				String key = e.getKey();
				List<?> value = e.getValue();
				BeanPropertyMeta bpm = getPropertyMeta(key);
				try {
					bpm.setArray(b, value);
				} catch (Exception e1) {
					throw new RuntimeException(e1);
				}
			}
			arrayPropertyCache = null;
		}

		// Initialize any null Optional<X> fields.
		for (BeanPropertyMeta pMeta : this.meta.properties.values()) {
			ClassMeta<?> cm = pMeta.getClassMeta();
			if (cm.isOptional() && pMeta.get(this, pMeta.getName()) == null)
				pMeta.set(this, pMeta.getName(), cm.getOptionalDefault());
		}

		return b;
	}

	/**
	 * Returns the wrapped bean object.
	 *
	 * <p>
	 * If <c>create</c> is <jk>false</jk>, then this method may return <jk>null</jk> if the bean has read-only
	 * properties set through a constructor defined by the {@link BeanConstructor @BeanConstructor} annotation.
	 *
	 * <p>
	 * This method does NOT always return the bean in it's final state.
	 * Array properties temporary stored as ArrayLists are not finalized until the {@link #getBean()} method is called.
	 *
	 * @param create If bean hasn't been instantiated yet, then instantiate it.
	 * @return The inner bean object.
	 */
	public T getBean(boolean create) {
		/** If this is a read-only bean, then we need to create it. */
		if (bean == null && create && meta.constructorArgs.length > 0) {
			String[] props = meta.constructorArgs;
			ConstructorInfo c = meta.constructor;
			Object[] args = new Object[props.length];
			for (int i = 0; i < props.length; i++)
				args[i] = propertyCache.remove(props[i]);
			try {
				bean = c.<T>invoke(args);
				for (Map.Entry<String,Object> e : propertyCache.entrySet())
					put(e.getKey(), e.getValue());
				propertyCache = null;
			} catch (IllegalArgumentException e) {
				throw new BeanRuntimeException(e, meta.classMeta.innerClass, "IllegalArgumentException occurred on call to class constructor ''{0}'' with argument types ''{1}''", c.getSimpleName(), SimpleJsonSerializer.DEFAULT.toString(ClassUtils.getClasses(args)));
			} catch (Exception e) {
				throw new BeanRuntimeException(e);
			}
		}
		return bean;
	}

	/**
	 * Sets a property on the bean.
	 *
	 * <p>
	 * If there is a {@link PojoSwap} associated with this bean property or bean property type class, then you must pass
	 * in a transformed value.
	 * For example, if the bean property type class is a {@link Date} and the bean property has the
	 * {@link org.apache.juneau.transforms.TemporalDateSwap.IsoInstant} swap associated with it through the
	 * {@link Swap#value() @Swap(value)} annotation, the value being passed in must be
	 * a String containing an ISO8601 date-time string value.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Construct a bean with a 'birthDate' Date field</jc>
	 * 	Person p = <jk>new</jk> Person();
	 *
	 * 	<jc>// Create a bean context and add the ISO8601 date-time swap</jc>
	 * 	BeanContext beanContext = <jk>new</jk> BeanContext().pojoSwaps(DateSwap.ISO8601DT.<jk>class</jk>);
	 *
	 * 	<jc>// Wrap our bean in a bean map</jc>
	 * 	BeanMap&lt;Person&gt; b = beanContext.forBean(p);
	 *
	 * 	<jc>// Set the field</jc>
	 * 	myBeanMap.put(<js>"birthDate"</js>, <js>"'1901-03-03T04:05:06-5000'"</js>);
	 * </p>
	 *
	 * @param property The name of the property to set.
	 * @param value The value to set the property to.
	 * @return
	 * 	If the bean context setting {@code beanMapPutReturnsOldValue} is <jk>true</jk>, then the old value of the
	 * 	property is returned.
	 * 	Otherwise, this method always returns <jk>null</jk>.
	 * @throws
	 * 	RuntimeException if any of the following occur.
	 * 	<ul>
	 * 		<li>BeanMapEntry does not exist on the underlying object.
	 * 		<li>Security settings prevent access to the underlying object setter method.
	 * 		<li>An exception occurred inside the setter method.
	 * 	</ul>
	 */
	@Override /* Map */
	public Object put(String property, Object value) {
		BeanPropertyMeta p = meta.properties.get(property);
		if (p == null) {
			if (meta.ctx.isIgnoreUnknownBeanProperties())
				return null;

			if (property.equals(beanTypePropertyName))
				return null;

			p = meta.properties.get("*");
			if (p == null)
				throw new BeanRuntimeException(meta.c, "Bean property ''{0}'' not found.", property);
		}
		if (meta.beanFilter != null)
			value = meta.beanFilter.writeProperty(this.bean, property, value);
		return p.set(this, property, value);
	}

	/**
	 * Add a value to a collection or array property.
	 *
	 * <p>
	 * As a general rule, adding to arrays is not recommended since the array must be recreate each time this method is
	 * called.
	 *
	 * @param property Property name or child-element name (if {@link Xml#childName() @Xml(childName)} is specified).
	 * @param value The value to add to the collection or array.
	 */
	public void add(String property, Object value) {
		BeanPropertyMeta p = meta.properties.get(property);
		if (p == null) {
			if (meta.ctx.isIgnoreUnknownBeanProperties())
				return;
			throw new BeanRuntimeException(meta.c, "Bean property ''{0}'' not found.", property);
		}
		p.add(this, property, value);
	}

	/**
	 * Gets a property on the bean.
	 *
	 * <p>
	 * If there is a {@link PojoSwap} associated with this bean property or bean property type class, then this method
	 * will return the transformed value.
	 * For example, if the bean property type class is a {@link Date} and the bean property has the
	 * {@link org.apache.juneau.transforms.TemporalDateSwap.IsoInstant} swap associated with it through the
	 * {@link Swap#value() @Swap(value)} annotation, this method will return a String containing an
	 * ISO8601 date-time string value.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Construct a bean with a 'birthDate' Date field</jc>
	 * 	Person p = <jk>new</jk> Person();
	 * 	p.setBirthDate(<jk>new</jk> Date(1, 2, 3, 4, 5, 6));
	 *
	 * 	<jc>// Create a bean context and add the ISO8601 date-time swap</jc>
	 * 	BeanContext beanContext = <jk>new</jk> BeanContext().pojoSwaps(DateSwap.ISO8601DT.<jk>class</jk>);
	 *
	 * 	<jc>// Wrap our bean in a bean map</jc>
	 * 	BeanMap&lt;Person&gt; b = beanContext.forBean(p);
	 *
	 * 	<jc>// Get the field as a string (i.e. "'1901-03-03T04:05:06-5000'")</jc>
	 * 	String s = myBeanMap.get(<js>"birthDate"</js>);
	 * </p>
	 *
	 * @param property The name of the property to get.
	 * @throws
	 * 	RuntimeException if any of the following occur.
	 * 	<ol>
	 * 		<li>BeanMapEntry does not exist on the underlying object.
	 * 		<li>Security settings prevent access to the underlying object getter method.
	 * 		<li>An exception occurred inside the getter method.
	 * 	</ol>
	 */
	@Override /* Map */
	public Object get(Object property) {
		String pName = stringify(property);
		BeanPropertyMeta p = getPropertyMeta(pName);
		if (p == null)
			return null;
		if (meta.beanFilter != null)
			return meta.beanFilter.readProperty(this.bean, pName, p.get(this, pName));
		return p.get(this, pName);
	}

	/**
	 * Same as {@link #get(Object)} except bypasses the POJO filter associated with the bean property or bean filter
	 * associated with the bean class.
	 *
	 * @param property The name of the property to get.
	 * @return The raw property value.
	 */
	public Object getRaw(Object property) {
		String pName = stringify(property);
		BeanPropertyMeta p = getPropertyMeta(pName);
		if (p == null)
			return null;
		return p.getRaw(this, pName);
	}

	/**
	 * Convenience method for setting multiple property values by passing in JSON text.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	aPersonBean.load(<js>"{name:'John Smith',age:21}"</js>)
	 * </p>
	 *
	 * @param input The text that will get parsed into a map and then added to this map.
	 * @return This object (for method chaining).
	 * @throws ParseException Malformed input encountered.
	 */
	public BeanMap<T> load(String input) throws ParseException {
		putAll(new ObjectMap(input));
		return this;
	}

	/**
	 * Convenience method for setting multiple property values by passing in a reader.
	 *
	 * @param r The text that will get parsed into a map and then added to this map.
	 * @param p The parser to use to parse the text.
	 * @return This object (for method chaining).
	 * @throws ParseException Malformed input encountered.
	 * @throws IOException Thrown by <c>Reader</c>.
	 */
	public BeanMap<T> load(Reader r, ReaderParser p) throws ParseException, IOException {
		putAll(new ObjectMap(r, p));
		return this;
	}

	/**
	 * Convenience method for loading this map with the contents of the specified map.
	 *
	 * <p>
	 * Identical to {@link #putAll(Map)} except as a fluent-style method.
	 *
	 * @param entries The map containing the entries to add to this map.
	 * @return This object (for method chaining).
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	public BeanMap<T> load(Map entries) {
		putAll(entries);
		return this;
	}

	/**
	 * Returns the names of all properties associated with the bean.
	 *
	 * <p>
	 * The returned set is unmodifiable.
	 */
	@Override /* Map */
	public Set<String> keySet() {
		if (meta.dynaProperty == null)
			return meta.properties.keySet();
		Set<String> l = new LinkedHashSet<>();
		for (String p : meta.properties.keySet())
			if (! "*".equals(p))
				l.add(p);
		try {
			l.addAll(meta.dynaProperty.getDynaMap(bean).keySet());
		} catch (Exception e) {
			throw new BeanRuntimeException(e);
		}
		return l;
	}

	/**
	 * Returns the specified property on this bean map.
	 *
	 * <p>
	 * Allows you to get and set an individual property on a bean without having a handle to the bean itself by using
	 * the {@link BeanMapEntry#getValue()} and {@link BeanMapEntry#setValue(Object)} methods.
	 *
	 * <p>
	 * This method can also be used to get metadata on a property by calling the {@link BeanMapEntry#getMeta()} method.
	 *
	 * @param propertyName The name of the property to look up.
	 * @return The bean property, or null if the bean has no such property.
	 */
	public BeanMapEntry getProperty(String propertyName) {
		BeanPropertyMeta p = getPropertyMeta(propertyName);
		if (p == null)
			return null;
		return new BeanMapEntry(this, p, propertyName);
	}

	/**
	 * Returns the metadata on the specified property.
	 *
	 * @param propertyName The name of the bean property.
	 * @return Metadata on the specified property, or <jk>null</jk> if that property does not exist.
	 */
	public BeanPropertyMeta getPropertyMeta(String propertyName) {
		BeanPropertyMeta bpMeta = meta.properties.get(propertyName);
		if (bpMeta == null)
			bpMeta = meta.dynaProperty;
		return bpMeta;
	}

	/**
	 * Returns the {@link ClassMeta} of the wrapped bean.
	 *
	 * @return The class type of the wrapped bean.
	 */
	@Override /* Delegate */
	public ClassMeta<T> getClassMeta() {
		return this.meta.getClassMeta();
	}

	/**
	 * Invokes all the getters on this bean and return the values as a list of {@link BeanPropertyValue} objects.
	 *
	 * <p>
	 * This allows a snapshot of all values to be grabbed from a bean in one call.
	 *
	 * @param ignoreNulls
	 * 	Don't return properties whose values are null.
	 * @param prependVals
	 * 	Additional bean property values to prepended to this list.
	 * 	Any <jk>null</jk> values in this list will be ignored.
	 * @return The list of all bean property values.
	 */
	public List<BeanPropertyValue> getValues(final boolean ignoreNulls, BeanPropertyValue...prependVals) {
		Collection<BeanPropertyMeta> properties = getProperties();
		int capacity = (ignoreNulls && properties.size() > 10) ? 10 : properties.size() + prependVals.length;
		List<BeanPropertyValue> l = new ArrayList<>(capacity);
		for (BeanPropertyValue v : prependVals)
			if (v != null)
				l.add(v);
		for (BeanPropertyMeta bpm : properties) {
			if (bpm.canRead()) {
				try {
					if (bpm.isDyna()) {
						Map<String,Object> dynaMap = bpm.getDynaMap(bean);
						if (dynaMap != null) {
							for (String pName : bpm.getDynaMap(bean).keySet()) {
								Object val = bpm.get(this, pName);
								if (val != null || ! ignoreNulls)
									l.add(new BeanPropertyValue(bpm, pName, val, null));
							}
						}
					} else {
						Object val = bpm.get(this, null);
						if (val != null || ! ignoreNulls)
							l.add(new BeanPropertyValue(bpm, bpm.getName(), val, null));
					}
				} catch (Error e) {
					// Errors should always be uncaught.
					throw e;
				} catch (Throwable t) {
					l.add(new BeanPropertyValue(bpm, bpm.getName(), null, t));
				}
			}
		}
		if (meta.sortProperties && meta.dynaProperty != null)
			Collections.sort(l);
		return l;
	}

	/**
	 * Given a string containing variables of the form <c>"{property}"</c>, replaces those variables with property
	 * values in this bean.
	 *
	 * @param s The string containing variables.
	 * @return A new string with variables replaced, or the same string if no variables were found.
	 */
	public String resolveVars(String s) {
		return StringUtils.replaceVars(s, this);
	}

	/**
	 * Returns a simple collection of properties for this bean map.
	 *
	 * @return A simple collection of properties for this bean map.
	 */
	protected Collection<BeanPropertyMeta> getProperties() {
		return meta.properties.values();
	}

	/**
	 * Returns all the properties associated with the bean.
	 *
	 * @return A new set.
	 */
	@Override
	public Set<Entry<String,Object>> entrySet() {

		// If this bean has a dyna-property, then we need to construct the entire set before returning.
		// Otherwise, we can create an iterator without a new data structure.
		if (meta.dynaProperty != null) {
			Set<Entry<String,Object>> s = new LinkedHashSet<>();
			for (BeanPropertyMeta pMeta : getProperties()) {
				if (pMeta.isDyna()) {
					try {
						for (Map.Entry<String,Object> e : pMeta.getDynaMap(bean).entrySet())
							s.add(new BeanMapEntry(this, pMeta, e.getKey()));
					} catch (Exception e) {
						throw new BeanRuntimeException(e);
					}
				} else {
					s.add(new BeanMapEntry(this, pMeta, pMeta.getName()));
				}
			}
			return s;
		}

		// Construct our own anonymous set to implement this function.
		Set<Entry<String,Object>> s = new AbstractSet<Entry<String,Object>>() {

			// Get the list of properties from the meta object.
			// Note that the HashMap.values() method caches results, so this collection
			// will really only be constructed once per bean type since the underlying
			// map never changes.
			final Collection<BeanPropertyMeta> pSet = getProperties();

			@Override /* Set */
			public Iterator<java.util.Map.Entry<String, Object>> iterator() {

				// Construct our own anonymous iterator that uses iterators against the meta.properties
				// map to maintain position.  This prevents us from having to construct any of our own
				// collection objects.
				return new Iterator<Entry<String,Object>>() {

					final Iterator<BeanPropertyMeta> pIterator = pSet.iterator();

					@Override /* Iterator */
					public boolean hasNext() {
						return pIterator.hasNext();
					}

					@Override /* Iterator */
					public Map.Entry<String, Object> next() {
						return new BeanMapEntry(BeanMap.this, pIterator.next(), null);
					}

					@Override /* Iterator */
					public void remove() {
						throw new UnsupportedOperationException("Cannot remove item from iterator.");
					}
				};
			}

			@Override /* Set */
			public int size() {
				return pSet.size();
			}
		};

		return s;
	}

	@SuppressWarnings("unchecked")
	void setBean(Object bean) {
		this.bean = (T)bean;
	}
}