// ***************************************************************************************************************************
// * 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 javax.xml.stream.XMLStreamConstants.*;

import java.util.*;

import javax.xml.stream.*;

import org.apache.juneau.parser.*;
import org.apache.juneau.xml.*;

/**
 * Predefined tags that occur in the serialized output of the HTML serializer.
 *
 * <ul class='seealso'>
 * 	<li class='link'>{@doc jm.HtmlDetails}
 * 	<li class='extlink'>{@source}
 * </ul>
 */
enum HtmlTag {

	TABLE(1,"<table>"),
	TR(2,"<tr>"),
	TH(3,"<th>"),
	TD(4,"<td>"),
	UL(5,"<ul>"),
	LI(6,"<li>"),
	STRING(7,"<string>"),
	NUMBER(8,"<number>"),
	BOOLEAN(9,"<boolean>"),
	NULL(10,"<null>"),
	A(11,"<a>"),
	BR(12,"<br>"),		// newline
	FF(13,"<ff>"),		// formfeed
	BS(14,"<bs>"),		// backspace
	SP(17, "<sp>"),   // space
	P(18, "<p>"),
	HTML(19, "<html>"),
	xTABLE(-1,"</table>"),
	xTR(-2,"</tr>"),
	xTH(-3,"</th>"),
	xTD(-4,"</td>"),
	xUL(-5,"</ul>"),
	xLI(-6,"</li>"),
	xSTRING(-7,"</string>"),
	xNUMBER(-8,"</number>"),
	xBOOLEAN(-9,"</boolean>"),
	xNULL(-10,"</null>"),
	xA(-11,"</a>"),
	xBR(-12,"</br>"),
	xFF(-13,"</ff>"),
	xBS(-14,"</bs>"),
	xSP(-17, "</sp>"),
	xP(-18, "</p>"),
	xHTML(-19, "</html>");

	private Map<Integer,HtmlTag> cache = new HashMap<>();

	int id;
	String label;

	HtmlTag(int id, String label) {
		this.id = id;
		this.label = label;
		cache.put(id, this);
	}

	static HtmlTag forEvent(ParserSession session, XMLStreamReader r) throws ParseException {
		int et = r.getEventType();
		if (et == START_ELEMENT)
			return forString(r.getLocalName(), false);
		else if (et == END_ELEMENT)
			return forString(r.getLocalName(), true);
		throw new ParseException(session, "Invalid call to HtmlTag.forEvent on event of type ''{0}''", XmlUtils.toReadableEvent(r));
	}

	static HtmlTag forString(String tag, boolean end) {
		char c = tag.charAt(0);
		HtmlTag t = null;
		if (c == 'u')
			t = (end ? xUL : UL);
		else if (c == 'l')
			t = (end ? xLI : LI);
		else if (c == 's') {
			c = tag.charAt(1);
			if (c == 'p')
				t = (end ? xSP : SP);
			else if (c == 't')
				t = (end ? xSTRING : STRING);
		}
		else if (c == 'b') {
			c = tag.charAt(1);
			if (c == 'o')
				t = (end ? xBOOLEAN : BOOLEAN);
			else if (c == 'r')
				t = (end ? xBR : BR);
			else if (c == 's')
				t = (end ? xBS : BS);
		}
		else if (c == 'a')
			t = (end ? xA : A);
		else if (c == 'n') {
			c = tag.charAt(2);
			if (c == 'm')
				t = (end ? xNUMBER : NUMBER);
			else if (c == 'l')
				t = (end ? xNULL : NULL);
		}
		else if (c == 't') {
			c = tag.charAt(1);
			if (c == 'a')
				t = (end ? xTABLE : TABLE);
			else if (c == 'r')
				t = (end ? xTR : TR);
			else if (c == 'h')
				t = (end ? xTH : TH);
			else if (c == 'd')
				t = (end ? xTD : TD);
		}
		else if (c == 'f')
			t = (end ? xFF : FF);
		else if (c == 'p')
			t = (end ? xP : P);
		else if (c == 'h')
			t = (end ? xHTML : HTML);
		return t;
	}

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

	public boolean isOneOf(HtmlTag...tags) {
		for (HtmlTag tag : tags)
			if (tag == this)
				return true;
		return false;
	}
}