// ***************************************************************************************************************************
// * 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 static org.apache.juneau.internal.ClassUtils.*;

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

import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.reflect.*;

/**
 * A one-time-use non-thread-safe object that's meant to be used once and then thrown away.
 *
 * <p>
 * Serializers and parsers use session objects to retrieve config properties and to use it as a scratchpad during
 * serialize and parse actions.
 */
public abstract class Session {

	private JuneauLogger logger;

	private final ObjectMap properties;
	private Map<String,Object> cache;
	private List<String> warnings;                 // Any warnings encountered.


	/**
	 * Default constructor.
	 *
	 * @param args
	 * 	Runtime arguments.
	 */
	protected Session(SessionArgs args) {
		this.properties = args.properties == null ? ObjectMap.EMPTY_MAP : args.properties;
	}

	/**
	 * Returns <jk>true</jk> if this session has the specified property defined.
	 *
	 * @param key The property key.
	 * @return <jk>true</jk> if this session has the specified property defined.
	 */
	public final boolean hasProperty(String key) {
		return properties != null && properties.containsKey(key);
	}

	/**
	 * Returns the session property with the specified key.
	 *
	 * <p>
	 * The returned type is the raw value of the property.
	 *
	 * @param key The property key.
	 * @return The session property, or <jk>null</jk> if the property does not exist.
	 */
	public final Object getProperty(String key) {
		if (properties == null)
			return null;
		return properties.get(key);
	}

	/**
	 * Returns the session property with the specified key and type.
	 *
	 * @param key The property key.
	 * @param type The type to convert the property to.
	 * @param def The default value if the session property does not exist or is <jk>null</jk>.
	 * @return The session property.
	 */
	@SuppressWarnings("unchecked")
	public final <T> T getProperty(String key, Class<T> type, T def) {
		if (properties == null)
			return def;
		Object o = properties.get(key);
		if (o == null)
			return def;
		type = (Class<T>)ClassInfo.of(type).getWrapperIfPrimitive();
		T t = properties.get(key, type);
		return t == null ? def : t;
	}

	/**
	 * Same as {@link #getProperty(String, Class, Object)} but allows for more than one default value.
	 *
	 * @param key The property key.
	 * @param type The type to convert the property to.
	 * @param def
	 * 	The default values if the session property does not exist or is <jk>null</jk>.
	 * 	The first non-null value is returned.
	 * @return The session property.
	 */
	@SafeVarargs
	public final <T> T getProperty(String key, Class<T> type, T...def) {
		return getProperty(key, type, ObjectUtils.firstNonNull(def));
	}

	/**
	 * Returns the session class property with the specified name.
	 *
	 * @param key The property name.
	 * @param type The class type of the property.
	 * @param def The default value.
	 * @return The property value, or the default value if it doesn't exist.
	 */
	@SuppressWarnings("unchecked")
	public final <T> Class<? extends T> getClassProperty(String key, Class<T> type, Class<? extends T> def) {
		return getProperty(key, Class.class, def);
	}

	/**
	 * Returns an instantiation of the specified class property.
	 *
	 * @param key The property name.
	 * @param type The class type of the property.
	 * @param def
	 * 	The default instance or class to instantiate if the property doesn't exist.
	 * @return A new property instance.
	 */
	public <T> T getInstanceProperty(String key, Class<T> type, Object def) {
		return newInstance(type, getProperty(key), def);
	}

	/**
	 * Returns the specified property as an array of instantiated objects.
	 *
	 * @param key The property name.
	 * @param type The class type of the property.
	 * @param def The default object to return if the property doesn't exist.
	 * @return A new property instance.
	 */
	@SuppressWarnings("unchecked")
	public <T> T[] getInstanceArrayProperty(String key, Class<T> type, T[] def) {
		Object o = getProperty(key);
		T[] t = null;
		if (o == null)
			t = def;
		else if (o.getClass().isArray()) {
			if (o.getClass().getComponentType() == type)
				t = (T[])o;
			else {
				t = (T[])Array.newInstance(type, Array.getLength(o));
				for (int i = 0; i < Array.getLength(o); i++)
					t[i] = newInstance(type, Array.get(o, i), null);
			}
		} else if (o instanceof Collection) {
			Collection<?> c = (Collection<?>)o;
			t = (T[])Array.newInstance(type, c.size());
			int i = 0;
			for (Object o2 : c)
				t[i++] = newInstance(type, o2, null);
		}
		if (t != null)
			return t;
		throw new ConfigException("Could not instantiate property ''{0}'' as type {1}", key, type);
	}

	/**
	 * Returns the session properties.
	 *
	 * @return The session properties passed in through the constructor.
	 */
	protected ObjectMap getProperties() {
		return properties;
	}

	/**
	 * Returns the session property keys.
	 *
	 * @return The session property keys passed in through the constructor.
	 */
	public Set<String> getPropertyKeys() {
		return properties.keySet();
	}

	@SuppressWarnings("unchecked")
	private <T> T newInstance(Class<T> type, Object o, Object def) {
		T t = null;
		if (o == null) {
			if (def == null)
				return null;
			t = castOrCreate(type, def);
		}
		else if (type.isInstance(o))
			t = (T)o;
		else if (o.getClass() == Class.class)
			t = castOrCreate(type, o);
		else if (o.getClass() == String.class)
			t = ClassUtils.fromString(type, o.toString());
		if (t != null)
			return t;
		throw new ConfigException("Could not instantiate type ''{0}'' as type {1}", o, type);
	}

	/**
	 * Adds an arbitrary object to this session's cache.
	 *
	 * <p>
	 * Can be used to store objects for reuse during a session.
	 *
	 * @param key The key.  Can be any string.
	 * @param val The cached object.
	 */
	public final void addToCache(String key, Object val) {
		if (cache == null)
			cache = new TreeMap<>();
		cache.put(key, val);
	}

	/**
	 * Adds arbitrary objects to this session's cache.
	 *
	 * <p>
	 * Can be used to store objects for reuse during a session.
	 *
	 * @param cacheObjects
	 * 	The objects to add to this session's cache.
	 * 	No-op if <jk>null</jk>.
	 */
	public final void addToCache(Map<String,Object> cacheObjects) {
		if (cacheObjects != null) {
			if (cache == null)
				cache = new TreeMap<>();
			cache.putAll(cacheObjects);
		}
	}

	/**
	 * Returns an object stored in the session cache.
	 *
	 * @param c The class type of the object.
	 * @param key The session object key.
	 * @return The cached object, or <jk>null</jk> if it doesn't exist.
	 */
	@SuppressWarnings("unchecked")
	public final <T> T getFromCache(Class<T> c, String key) {
		return cache == null ? null : (T)cache.get(key);
	}

	/**
	 * Logs a warning message.
	 *
	 * @param msg The warning message.
	 * @param args Optional {@link MessageFormat}-style arguments.
	 */
	public final void addWarning(String msg, Object... args) {
		if (warnings == null)
			warnings = new LinkedList<>();
		getLogger().warning(msg, args);
		warnings.add((warnings.size() + 1) + ": " + format(msg, args));
	}

	/**
	 * Returns <jk>true</jk> if warnings occurred in this session.
	 *
	 * @return <jk>true</jk> if warnings occurred in this session.
	 */
	public final boolean hasWarnings() {
		return warnings != null && warnings.size() > 0;
	}

	/**
	 * Returns the warnings that occurred in this session.
	 *
	 * @return The warnings that occurred in this session, or <jk>null</jk> if no warnings occurred.
	 */
	public final List<String> getWarnings() {
		return warnings;
	}

	/**
	 * Returns the logger associated with this session.
	 *
	 * <p>
	 * Subclasses can override this method to provide their own logger.
	 *
	 * @return The logger associated with this session.
	 */
	protected final JuneauLogger getLogger() {
		if (logger == null)
			logger = JuneauLogger.getLogger(getClass());
		return logger;
	}

	/**
	 * Throws a {@link BeanRuntimeException} if any warnings occurred in this session.
	 */
	public void checkForWarnings() {
		if (warnings != null && ! warnings.isEmpty())
			throw new BeanRuntimeException("Warnings occurred in session: \n" + join(getWarnings(), "\n"));
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Other methods
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Returns the properties defined on this bean context as a simple map for debugging purposes.
	 *
	 * @return A new map containing the properties defined on this context.
	 */
	public ObjectMap toMap() {
		return new DefaultFilteringObjectMap();
	}

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