// ***************************************************************************************************************************
// * 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.html;

import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ObjectUtils.*;
import static org.apache.juneau.xml.XmlSerializerSession.ContentResult.*;

import java.io.*;
import java.util.*;
import java.util.regex.*;

import org.apache.juneau.*;
import org.apache.juneau.html.annotation.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.transform.*;
import org.apache.juneau.xml.*;
import org.apache.juneau.xml.annotation.*;

/**
 * Session object that lives for the duration of a single use of {@link HtmlSerializer}.
 *
 * <p>
 * This class is NOT thread safe.
 * It is typically discarded after one-time use although it can be reused within the same thread.
 */
public class HtmlSerializerSession extends XmlSerializerSession {

	private final HtmlSerializer ctx;
	private final Pattern urlPattern = Pattern.compile("http[s]?\\:\\/\\/.*");
	private final Pattern labelPattern;


	/**
	 * Create a new session using properties specified in the context.
	 *
	 * @param ctx
	 * 	The context creating this session object.
	 * 	The context contains all the configuration settings for this object.
	 * @param args
	 * 	Runtime arguments.
	 * 	These specify session-level information such as locale and URI context.
	 * 	It also include session-level properties that override the properties defined on the bean and
	 * 	serializer contexts.
	 */
	protected HtmlSerializerSession(HtmlSerializer ctx, SerializerSessionArgs args) {
		super(ctx, args);
		this.ctx = ctx;
		labelPattern = Pattern.compile("[\\?\\&]" + Pattern.quote(ctx.getLabelParameter()) + "=([^\\&]*)");
	}

	/**
	 * Converts the specified output target object to an {@link HtmlWriter}.
	 *
	 * @param out The output target object.
	 * @return The output target object wrapped in an {@link HtmlWriter}.
	 * @throws IOException Thrown by underlying stream.
	 */
	protected final HtmlWriter getHtmlWriter(SerializerPipe out) throws IOException {
		Object output = out.getRawOutput();
		if (output instanceof HtmlWriter)
			return (HtmlWriter)output;
		HtmlWriter w = new HtmlWriter(out.getWriter(), isUseWhitespace(), getMaxIndent(), isTrimStrings(), getQuoteChar(),
			getUriResolver());
		out.setWriter(w);
		return w;
	}

	/**
	 * Returns <jk>true</jk> if the specified object is a URL.
	 *
	 * @param cm The ClassMeta of the object being serialized.
	 * @param pMeta
	 * 	The property metadata of the bean property of the object.
	 * 	Can be <jk>null</jk> if the object isn't from a bean property.
	 * @param o The object.
	 * @return <jk>true</jk> if the specified object is a URL.
	 */
	public boolean isUri(ClassMeta<?> cm, BeanPropertyMeta pMeta, Object o) {
		if (cm.isUri())
			return true;
		if (pMeta != null && pMeta.isUri())
			return true;
		if (isDetectLinksInStrings() && o instanceof CharSequence && urlPattern.matcher(o.toString()).matches())
			return true;
		return false;
	}

	/**
	 * Returns the anchor text to use for the specified URL object.
	 *
	 * @param pMeta
	 * 	The property metadata of the bean property of the object.
	 * 	Can be <jk>null</jk> if the object isn't from a bean property.
	 * @param o The URL object.
	 * @return The anchor text to use for the specified URL object.
	 */
	public String getAnchorText(BeanPropertyMeta pMeta, Object o) {
		String s = o.toString();
		if (isDetectLabelParameters()) {
			Matcher m = labelPattern.matcher(s);
			if (m.find())
				return urlDecode(m.group(1));
		}
		switch (getUriAnchorText()) {
			case LAST_TOKEN:
				s = resolveUri(s);
				if (s.indexOf('/') != -1)
					s = s.substring(s.lastIndexOf('/')+1);
				if (s.indexOf('?') != -1)
					s = s.substring(0, s.indexOf('?'));
				if (s.indexOf('#') != -1)
					s = s.substring(0, s.indexOf('#'));
				if (s.isEmpty())
					s = "/";
				return urlDecode(s);
			case URI_ANCHOR:
				if (s.indexOf('#') != -1)
					s = s.substring(s.lastIndexOf('#')+1);
				return urlDecode(s);
			case PROPERTY_NAME:
				return pMeta == null ? s : pMeta.getName();
			case URI:
				return resolveUri(s);
			case CONTEXT_RELATIVE:
				return relativizeUri("context:/", s);
			case SERVLET_RELATIVE:
				return relativizeUri("servlet:/", s);
			case PATH_RELATIVE:
				return relativizeUri("request:/", s);
			default /* TO_STRING */:
				return s;
		}
	}

	@Override /* XmlSerializer */
	public boolean isHtmlMode() {
		return true;
	}

	@Override /* Serializer */
	protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {
		doSerialize(o, getHtmlWriter(out));
	}

	/**
	 * Main serialization routine.
	 *
	 * @param session The serialization context object.
	 * @param o The object being serialized.
	 * @param w The writer to serialize to.
	 * @return The same writer passed in.
	 * @throws IOException If a problem occurred trying to send output to the writer.
	 */
	private XmlWriter doSerialize(Object o, XmlWriter w) throws IOException, SerializeException {
		serializeAnything(w, o, getExpectedRootType(o), null, null, getInitialDepth()-1, true, false);
		return w;
	}

	@SuppressWarnings({ "rawtypes" })
	@Override /* XmlSerializerSession */
	protected ContentResult serializeAnything(
			XmlWriter out,
			Object o,
			ClassMeta<?> eType,
			String elementName,
			Namespace elementNamespace,
			boolean addNamespaceUris,
			XmlFormat format,
			boolean isMixed,
			boolean preserveWhitespace,
			BeanPropertyMeta pMeta) throws IOException, SerializeException {

		// If this is a bean, then we want to serialize it as HTML unless it's @Html(format=XML).
		ClassMeta<?> type = push2(elementName, o, eType);
		pop();

		if (type == null)
			type = object();
		else if (type.isDelegate())
			type = ((Delegate)o).getClassMeta();
		PojoSwap swap = type.getPojoSwap(this);
		if (swap != null) {
			o = swap(swap, o);
			type = swap.getSwapClassMeta(this);
			if (type.isObject())
				type = getClassMetaForObject(o);
		}

		HtmlClassMeta cHtml = getHtmlClassMeta(type);

		if (type.isMapOrBean() && ! cHtml.isXml())
			return serializeAnything(out, o, eType, elementName, pMeta, 0, false, false);

		return super.serializeAnything(out, o, eType, elementName, elementNamespace, addNamespaceUris, format, isMixed, preserveWhitespace, pMeta);
	}
	/**
	 * Serialize the specified object to the specified writer.
	 *
	 * @param out The writer.
	 * @param o The object to serialize.
	 * @param eType The expected type of the object if this is a bean property.
	 * @param name
	 * 	The attribute name of this object if this object was a field in a JSON object (i.e. key of a
	 * 	{@link java.util.Map.Entry} or property name of a bean).
	 * @param pMeta The bean property being serialized, or <jk>null</jk> if we're not serializing a bean property.
	 * @param xIndent The current indentation value.
	 * @param isRoot <jk>true</jk> if this is the root element of the document.
	 * @param nlIfElement <jk>true</jk> if we should add a newline to the output before serializing only if the object is an element and not text.
	 * @return The type of content encountered.  Either simple (no whitespace) or normal (elements with whitespace).
	 * @throws IOException Thrown by underlying stream.
	 * @throws SerializeException Generic serialization error occurred.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected ContentResult serializeAnything(XmlWriter out, Object o,
			ClassMeta<?> eType, String name, BeanPropertyMeta pMeta, int xIndent, boolean isRoot, boolean nlIfElement) throws IOException, SerializeException {

		ClassMeta<?> aType = null;       // The actual type
		ClassMeta<?> wType = null;     // The wrapped type (delegate)
		ClassMeta<?> sType = object();   // The serialized type

		if (eType == null)
			eType = object();

		aType = push2(name, o, eType);

		// Handle recursion
		if (aType == null) {
			o = null;
			aType = object();
		}

		// Handle Optional<X>
		if (isOptional(aType)) {
			o = getOptionalValue(o);
			eType = getOptionalType(eType);
			aType = getClassMetaForObject(o, object());
		}

		indent += xIndent;

		ContentResult cr = CR_ELEMENTS;

		// Determine the type.
		if (o == null || (aType.isChar() && ((Character)o).charValue() == 0)) {
			out.tag("null");
			cr = ContentResult.CR_MIXED;

		} else {

			if (aType.isDelegate()) {
				wType = aType;
				aType = ((Delegate)o).getClassMeta();
			}

			sType = aType;

			String typeName = null;
			if (isAddBeanTypes() && ! eType.equals(aType))
				typeName = aType.getDictionaryName();

			// Swap if necessary
			PojoSwap swap = aType.getPojoSwap(this);
			if (swap != null) {
				o = swap(swap, o);
				sType = swap.getSwapClassMeta(this);

				// If the getSwapClass() method returns Object, we need to figure out
				// the actual type now.
				if (sType.isObject())
					sType = getClassMetaForObject(o);
			}

			// Handle the case where we're serializing a raw stream.
			if (sType.isReader() || sType.isInputStream()) {
				pop();
				indent -= xIndent;
				IOUtils.pipe(o, out);
				return ContentResult.CR_MIXED;
			}

			HtmlClassMeta cHtml = getHtmlClassMeta(sType);
			HtmlBeanPropertyMeta bpHtml = getHtmlBeanPropertyMeta(pMeta);

			HtmlRender render = firstNonNull(bpHtml.getRender(), cHtml.getRender());

			if (render != null) {
				Object o2 = render.getContent(this, o);
				if (o2 != o) {
					indent -= xIndent;
					pop();
					out.nl(indent);
					return serializeAnything(out, o2, null, typeName, null, xIndent, false, false);
				}
			}

			if (cHtml.isXml() || bpHtml.isXml()) {
				pop();
				indent++;
				if (nlIfElement)
					out.nl(0);
				super.serializeAnything(out, o, null, null, null, false, XmlFormat.MIXED, false, false, null);
				indent -= xIndent+1;
				return cr;

			} else if (cHtml.isPlainText() || bpHtml.isPlainText()) {
				out.write(o == null ? "null" : o.toString());
				cr = CR_MIXED;

			} else if (o == null || (sType.isChar() && ((Character)o).charValue() == 0)) {
				out.tag("null");
				cr = CR_MIXED;

			} else if (sType.isNumber()) {
				if (eType.isNumber() && ! isRoot)
					out.append(o);
				else
					out.sTag("number").append(o).eTag("number");
				cr = CR_MIXED;

			} else if (sType.isBoolean()) {
				if (eType.isBoolean() && ! isRoot)
					out.append(o);
				else
					out.sTag("boolean").append(o).eTag("boolean");
				cr = CR_MIXED;

			} else if (sType.isMap() || (wType != null && wType.isMap())) {
				out.nlIf(! isRoot, xIndent+1);
				if (o instanceof BeanMap)
					serializeBeanMap(out, (BeanMap)o, eType, pMeta);
				else
					serializeMap(out, (Map)o, sType, eType.getKeyType(), eType.getValueType(), typeName, pMeta);

			} else if (sType.isBean()) {
				BeanMap m = toBeanMap(o);
				if (aType.hasAnnotation(HtmlLink.class)) {
					HtmlLink h = aType.getAnnotation(HtmlLink.class);
					Object urlProp = m.get(h.uriProperty());
					Object nameProp = m.get(h.nameProperty());
					out.oTag("a").attrUri("href", urlProp).append('>').text(nameProp).eTag("a");
					cr = CR_MIXED;
				} else {
					out.nlIf(! isRoot, xIndent+2);
					serializeBeanMap(out, m, eType, pMeta);
				}

			} else if (sType.isCollection() || sType.isArray() || (wType != null && wType.isCollection())) {
				out.nlIf(! isRoot, xIndent+1);
				serializeCollection(out, o, sType, eType, name, pMeta);

			} else if (isUri(sType, pMeta, o)) {
				String label = getAnchorText(pMeta, o);
				out.oTag("a").attrUri("href", o).append('>');
				out.text(label);
				out.eTag("a");
				cr = CR_MIXED;

			} else {
				if (isRoot)
					out.sTag("string").text(toString(o)).eTag("string");
				else
					out.text(toString(o));
				cr = CR_MIXED;
			}
		}
		pop();
		indent -= xIndent;
		return cr;
	}

	@SuppressWarnings({ "rawtypes" })
	private void serializeMap(XmlWriter out, Map m, ClassMeta<?> sType,
			ClassMeta<?> eKeyType, ClassMeta<?> eValueType, String typeName, BeanPropertyMeta ppMeta) throws IOException, SerializeException {

		ClassMeta<?> keyType = eKeyType == null ? string() : eKeyType;
		ClassMeta<?> valueType = eValueType == null ? object() : eValueType;
		ClassMeta<?> aType = getClassMetaForObject(m);       // The actual type
		HtmlClassMeta cHtml = getHtmlClassMeta(aType);
		HtmlBeanPropertyMeta bpHtml = getHtmlBeanPropertyMeta(ppMeta);

		int i = indent;

		out.oTag(i, "table");

		if (typeName != null && ppMeta != null && ppMeta.getClassMeta() != aType)
			out.attr(getBeanTypePropertyName(sType), typeName);

		out.append(">").nl(i+1);
		if (isAddKeyValueTableHeaders() && ! (cHtml.isNoTableHeaders() || bpHtml.isNoTableHeaders())) {
			out.sTag(i+1, "tr").nl(i+2);
			out.sTag(i+2, "th").append("key").eTag("th").nl(i+3);
			out.sTag(i+2, "th").append("value").eTag("th").nl(i+3);
			out.ie(i+1).eTag("tr").nl(i+2);
		}
		for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) {

			Object key = generalize(e.getKey(), keyType);
			Object value = null;
			try {
				value = e.getValue();
			} catch (StackOverflowError t) {
				throw t;
			} catch (Throwable t) {
				onError(t, "Could not call getValue() on property ''{0}'', {1}", e.getKey(), t.getLocalizedMessage());
			}

			String link = getLink(ppMeta);
			String style = getStyle(this, ppMeta, value);

			out.sTag(i+1, "tr").nl(i+2);
			out.oTag(i+2, "td");
			if (style != null)
				out.attr("style", style);
			out.cTag();
			if (link != null)
				out.oTag(i+3, "a").attrUri("href", link.replace("{#}", stringify(value))).cTag();
			ContentResult cr = serializeAnything(out, key, keyType, null, null, 2, false, false);
			if (link != null)
				out.eTag("a");
			if (cr == CR_ELEMENTS)
				out.i(i+2);
			out.eTag("td").nl(i+2);
			out.sTag(i+2, "td");
			cr = serializeAnything(out, value, valueType, (key == null ? "_x0000_" : toString(key)), null, 2, false, false);
			if (cr == CR_ELEMENTS)
				out.ie(i+2);
			out.eTag("td").nl(i+2);
			out.ie(i+1).eTag("tr").nl(i+1);
		}
		out.ie(i).eTag("table").nl(i);
	}

	private void serializeBeanMap(XmlWriter out, BeanMap<?> m, ClassMeta<?> eType, BeanPropertyMeta ppMeta) throws IOException, SerializeException {

		HtmlClassMeta cHtml = getHtmlClassMeta(m.getClassMeta());
		HtmlBeanPropertyMeta bpHtml = getHtmlBeanPropertyMeta(ppMeta);

		int i = indent;

		out.oTag(i, "table");

		String typeName = m.getMeta().getDictionaryName();
		if (typeName != null && eType != m.getClassMeta())
			out.attr(getBeanTypePropertyName(m.getClassMeta()), typeName);

		out.append('>').nl(i);
		if (isAddKeyValueTableHeaders() && ! (cHtml.isNoTableHeaders() || bpHtml.isNoTableHeaders())) {
			out.sTag(i+1, "tr").nl(i+1);
			out.sTag(i+2, "th").append("key").eTag("th").nl(i+2);
			out.sTag(i+2, "th").append("value").eTag("th").nl(i+2);
			out.ie(i+1).eTag("tr").nl(i+1);
		}

		for (BeanPropertyValue p : m.getValues(isTrimNullProperties())) {
			BeanPropertyMeta pMeta = p.getMeta();
			ClassMeta<?> cMeta = p.getClassMeta();

			String key = p.getName();
			Object value = p.getValue();
			Throwable t = p.getThrown();
			if (t != null)
				onBeanGetterException(pMeta, t);

			if (canIgnoreValue(cMeta, key, value))
				continue;

			String link = null, anchorText = null;
			if (! cMeta.isCollectionOrArray()) {
				link = m.resolveVars(getLink(pMeta));
				anchorText = m.resolveVars(getAnchorText(pMeta));
			}

			if (anchorText != null)
				value = anchorText;

			out.sTag(i+1, "tr").nl(i+1);
			out.sTag(i+2, "td").text(key).eTag("td").nl(i+2);
			out.oTag(i+2, "td");
			String style = getStyle(this, pMeta, value);
			if (style != null)
				out.attr("style", style);
			out.cTag();

			try {
				if (link != null)
					out.oTag(i+3, "a").attrUri("href", link).cTag();
				ContentResult cr = serializeAnything(out, value, cMeta, key, pMeta, 2, false, true);
				if (cr == CR_ELEMENTS)
					out.i(i+2);
				if (link != null)
					out.eTag("a");
			} catch (SerializeException e) {
				throw e;
			} catch (Error e) {
				throw e;
			} catch (Throwable e) {
				e.printStackTrace();
				onBeanGetterException(pMeta, e);
			}
			out.eTag("td").nl(i+2);
			out.ie(i+1).eTag("tr").nl(i+1);
		}
		out.ie(i).eTag("table").nl(i);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void serializeCollection(XmlWriter out, Object in, ClassMeta<?> sType, ClassMeta<?> eType, String name, BeanPropertyMeta ppMeta) throws IOException, SerializeException {

		HtmlClassMeta cHtml = getHtmlClassMeta(sType);
		HtmlBeanPropertyMeta bpHtml = getHtmlBeanPropertyMeta(ppMeta);

		Collection c = (sType.isCollection() ? (Collection)in : toList(sType.getInnerClass(), in));

		boolean isCdc = cHtml.isHtmlCdc() || bpHtml.isHtmlCdc();
		boolean isSdc = cHtml.isHtmlSdc() || bpHtml.isHtmlSdc();
		boolean isDc = isCdc || isSdc;

		int i = indent;
		if (c.isEmpty()) {
			out.appendln(i, "<ul></ul>");
			return;
		}

		String type2 = null;
		if (sType != eType)
			type2 = sType.getDictionaryName();
		if (type2 == null)
			type2 = "array";

		c = sort(c);

		String btpn = getBeanTypePropertyName(eType);

		// Look at the objects to see how we're going to handle them.  Check the first object to see how we're going to
		// handle this.
		// If it's a map or bean, then we'll create a table.
		// Otherwise, we'll create a list.
		Object[] th = getTableHeaders(c, bpHtml);

		if (th != null) {

			out.oTag(i, "table").attr(btpn, type2).append('>').nl(i+1);
			out.sTag(i+1, "tr").nl(i+2);
			for (Object key : th) {
				out.sTag(i+2, "th");
				out.text(convertToType(key, String.class));
				out.eTag("th").nl(i+2);
			}
			out.ie(i+1).eTag("tr").nl(i+1);

			for (Object o : c) {
				ClassMeta<?> cm = getClassMetaForObject(o);

				if (cm != null && cm.getPojoSwap(this) != null) {
					PojoSwap swap = cm.getPojoSwap(this);
					o = swap(swap, o);
					cm = swap.getSwapClassMeta(this);
				}

				out.oTag(i+1, "tr");
				String typeName = (cm == null ? null : cm.getDictionaryName());
				String typeProperty = getBeanTypePropertyName(cm);

				if (typeName != null && eType.getElementType() != cm)
					out.attr(typeProperty, typeName);
				out.cTag().nl(i+2);

				if (cm == null) {
					out.i(i+2);
					serializeAnything(out, o, null, null, null, 1, false, false);
					out.nl(0);

				} else if (cm.isMap() && ! (cm.isBeanMap())) {
					Map m2 = sort((Map)o);

					for (Object k : th) {
						out.sTag(i+2, "td");
						ContentResult cr = serializeAnything(out, m2.get(k), eType.getElementType(), toString(k), null, 2, false, true);
						if (cr == CR_ELEMENTS)
							out.i(i+2);
						out.eTag("td").nl(i+2);
					}
				} else {
					BeanMap m2 = null;
					if (o instanceof BeanMap)
						m2 = (BeanMap)o;
					else
						m2 = toBeanMap(o);

					for (Object k : th) {
						BeanMapEntry p = m2.getProperty(toString(k));
						BeanPropertyMeta pMeta = p.getMeta();
						if (pMeta.canRead()) {
							Object value = p.getValue();

							String link = null, anchorText = null;
							if (! pMeta.getClassMeta().isCollectionOrArray()) {
								link = m2.resolveVars(getLink(pMeta));
								anchorText = m2.resolveVars(getAnchorText(pMeta));
							}

							if (anchorText != null)
								value = anchorText;

							String style = getStyle(this, pMeta, value);
							out.oTag(i+2, "td");
							if (style != null)
								out.attr("style", style);
							out.cTag();
							if (link != null)
								out.oTag("a").attrUri("href", link).cTag();
							ContentResult cr = serializeAnything(out, value, pMeta.getClassMeta(), p.getKey().toString(), pMeta, 2, false, true);
							if (cr == CR_ELEMENTS)
								out.i(i+2);
							if (link != null)
								out.eTag("a");
							out.eTag("td").nl(i+2);
						}
					}
				}
				out.ie(i+1).eTag("tr").nl(i+1);
			}
			out.ie(i).eTag("table").nl(i);

		} else {
			out.oTag(i, isDc ? "p" : "ul");
			if (! type2.equals("array"))
				out.attr(btpn, type2);
			out.append('>').nl(i+1);
			boolean isFirst = true;
			for (Object o : c) {
				if (isDc && ! isFirst)
					out.append(isCdc ? ", " : " ");
				if (! isDc)
					out.oTag(i+1, "li");
				String style = getStyle(this, ppMeta, o);
				String link = getLink(ppMeta);
				if (style != null && ! isDc)
					out.attr("style", style);
				if (! isDc)
					out.cTag();
				if (link != null)
					out.oTag(i+2, "a").attrUri("href", link.replace("{#}", stringify(o))).cTag();
				ContentResult cr = serializeAnything(out, o, eType.getElementType(), name, null, 1, false, true);
				if (link != null)
					out.eTag("a");
				if (cr == CR_ELEMENTS)
					out.ie(i+1);
				if (! isDc)
					out.eTag("li").nl(i+1);
				isFirst = false;
			}
			out.ie(i).eTag(isDc ? "p" : "ul").nl(i);
		}
	}

	private HtmlRender<?> getRender(HtmlSerializerSession session, BeanPropertyMeta pMeta, Object value) {
		if (pMeta == null)
			return null;
		HtmlRender<?> render = getHtmlBeanPropertyMeta(pMeta).getRender();
		if (render != null)
			return render;
		ClassMeta<?> cMeta = session.getClassMetaForObject(value);
		render = cMeta == null ? null : getHtmlClassMeta(cMeta).getRender();
		return render;
	}

	@SuppressWarnings({"rawtypes","unchecked"})
	private String getStyle(HtmlSerializerSession session, BeanPropertyMeta pMeta, Object value) {
		HtmlRender render = getRender(session, pMeta, value);
		return render == null ? null : render.getStyle(session, value);
	}

	private String getLink(BeanPropertyMeta pMeta) {
		return pMeta == null ? null : getHtmlBeanPropertyMeta(pMeta).getLink();
	}

	private String getAnchorText(BeanPropertyMeta pMeta) {
		return pMeta == null ? null : getHtmlBeanPropertyMeta(pMeta).getAnchorText();
	}

	/*
	 * Returns the table column headers for the specified collection of objects.
	 * Returns null if collection should not be serialized as a 2-dimensional table.
	 * 2-dimensional tables are used for collections of objects that all have the same set of property names.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Object[] getTableHeaders(Collection c, HtmlBeanPropertyMeta bpHtml) throws SerializeException  {
		if (c.size() == 0)
			return null;
		c = sort(c);
		Object[] th;
		Set<ClassMeta> prevC = new HashSet<>();
		Object o1 = null;
		for (Object o : c)
			if (o != null) {
				o1 = o;
				break;
			}
		if (o1 == null)
			return null;
		ClassMeta<?> cm = getClassMetaForObject(o1);

		PojoSwap swap = cm.getPojoSwap(this);
		if (swap != null) {
			o1 = swap(swap, o1);
			cm = swap.getSwapClassMeta(this);
		}

		if (cm == null || ! cm.isMapOrBean())
			return null;
		if (cm.getInnerClass().isAnnotationPresent(HtmlLink.class))
			return null;

		HtmlClassMeta cHtml = getHtmlClassMeta(cm);

		if (cHtml.isNoTables() || bpHtml.isNoTables())
			return null;
		if (cHtml.isNoTableHeaders() || bpHtml.isNoTableHeaders())
			return new Object[0];
		if (canIgnoreValue(cm, null, o1))
			return null;
		if (cm.isMap() && ! cm.isBeanMap()) {
			Set<Object> set = new LinkedHashSet<>();
			for (Object o : c) {
				if (! canIgnoreValue(cm, null, o)) {
					if (! cm.isInstance(o))
						return null;
					Map m = sort((Map)o);
					for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) {
						if (e.getValue() != null)
							set.add(e.getKey() == null ? null : e.getKey());
					}
				}
			}
			th = set.toArray(new Object[set.size()]);
		} else {
			Map<String,Boolean> m = new LinkedHashMap<>();
			for (Object o : c) {
				if (! canIgnoreValue(cm, null, o)) {
					if (! cm.isInstance(o))
						return null;
					BeanMap<?> bm = (o instanceof BeanMap ? (BeanMap)o : toBeanMap(o));
					for (Map.Entry<String,Object> e : bm.entrySet()) {
						String key = e.getKey();
						if (e.getValue() != null)
							m.put(key, true);
						else if (! m.containsKey(key))
							m.put(key, false);
					}
				}
			}
			for (Iterator<Boolean> i = m.values().iterator(); i.hasNext();)
				if (! i.next())
					i.remove();
			th = m.keySet().toArray(new Object[m.size()]);
		}
		prevC.add(cm);
		boolean isSortable = true;
		for (Object o : th)
			isSortable &= (o instanceof Comparable);
		Set<Object> s = (isSortable ? new TreeSet<>() : new LinkedHashSet<>());
		s.addAll(Arrays.asList(th));

		for (Object o : c) {
			if (o == null)
				continue;
			cm = getClassMetaForObject(o);

			PojoSwap ps = cm == null ? null : cm.getPojoSwap(this);
			if (ps != null) {
				o = swap(ps, o);
				cm = ps.getSwapClassMeta(this);
			}
			if (prevC.contains(cm))
				continue;
			if (cm == null || ! (cm.isMap() || cm.isBean()))
				return null;
			if (cm.getInnerClass().isAnnotationPresent(HtmlLink.class))
				return null;
			if (canIgnoreValue(cm, null, o))
				return null;
			if (cm.isMap() && ! cm.isBeanMap()) {
				Map m = (Map)o;
				if (th.length != m.keySet().size())
					return null;
				for (Object k : m.keySet())
					if (! s.contains(k.toString()))
						return null;
			} else {
				BeanMap<?> bm = (o instanceof BeanMap ? (BeanMap)o : toBeanMap(o));
				int l = 0;
				for (String k : bm.keySet()) {
					if (! s.contains(k))
						return null;
					l++;
				}
				if (s.size() != l)
					return null;
			}
		}
		return th;
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Properties
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Configuration property:  Add <js>"_type"</js> properties when needed.
	 *
	 * @see HtmlSerializer#HTML_addBeanTypes
	 * @return
	 * 	<jk>true</jk> if <js>"_type"</js> properties will be added to beans if their type cannot be inferred
	 * 	through reflection.
	 */
	@Override
	protected final boolean isAddBeanTypes() {
		return ctx.isAddBeanTypes();
	}

	/**
	 * Configuration property:  Add key/value headers on bean/map tables.
	 *
	 * @see HtmlSerializer#HTML_addKeyValueTableHeaders
	 * @return
	 * 	<jk>true</jk> if <bc>key</bc> and <bc>value</bc> column headers are added to tables.
	 */
	protected final boolean isAddKeyValueTableHeaders() {
		return ctx.isAddKeyValueTableHeaders();
	}

	/**
	 * Configuration property:  Look for link labels in URIs.
	 *
	 * @see HtmlSerializer#HTML_detectLabelParameters
	 * @return
	 * 	<jk>true</jk> if we should look for URL label parameters (e.g. <js>"?label=foobar"</js>).
	 */
	protected final boolean isDetectLabelParameters() {
		return ctx.isDetectLabelParameters();
	}

	/**
	 * Configuration property:  Look for URLs in {@link String Strings}.
	 *
	 * @see HtmlSerializer#HTML_detectLinksInStrings
	 * @return
	 * 	<jk>true</jk> if we should automatically convert strings to URLs if they look like a URL.
	 */
	protected final boolean isDetectLinksInStrings() {
		return ctx.isDetectLinksInStrings();
	}

	/**
	 * Configuration property:  Link label parameter name.
	 *
	 * @see HtmlSerializer#HTML_labelParameter
	 * @return
	 * 	The parameter name to look for when resolving link labels via {@link HtmlSerializer#HTML_detectLabelParameters}.
	 */
	protected final String getLabelParameter() {
		return ctx.getLabelParameter();
	}

	/**
	 * Configuration property:  Anchor text source.
	 *
	 * @see HtmlSerializer#HTML_uriAnchorText
	 * @return
	 * 	When creating anchor tags (e.g. <code><xt>&lt;a</xt> <xa>href</xa>=<xs>'...'</xs>
	 * 	<xt>&gt;</xt>text<xt>&lt;/a&gt;</xt></code>) in HTML, this setting defines what to set the inner text to.
	 */
	protected final AnchorText getUriAnchorText() {
		return ctx.getUriAnchorText();
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Extended metadata
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Returns the language-specific metadata on the specified class.
	 *
	 * @param cm The class to return the metadata on.
	 * @return The metadata.
	 */
	protected HtmlClassMeta getHtmlClassMeta(ClassMeta<?> cm) {
		return ctx.getHtmlClassMeta(cm);
	}

	/**
	 * Returns the language-specific metadata on the specified bean property.
	 *
	 * @param bpm The bean property to return the metadata on.
	 * @return The metadata.
	 */
	protected HtmlBeanPropertyMeta getHtmlBeanPropertyMeta(BeanPropertyMeta bpm) {
		return ctx.getHtmlBeanPropertyMeta(bpm);
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Other methods
	//-----------------------------------------------------------------------------------------------------------------

	@Override /* Session */
	public ObjectMap toMap() {
		return super.toMap()
			.append("HtmlSerializerSession", new DefaultFilteringObjectMap()
		);
	}
}
