/*******************************************************************************
 *  Copyright (c) 2007, 2017 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 * 
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.persistence;

import static java.util.stream.Collectors.joining;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.eclipse.equinox.p2.metadata.Version;

public class XMLWriter implements XMLConstants {

	public static class ProcessingInstruction {

		private String target;
		private String[] data;

		// The standard UTF-8 processing instruction
		public static final String XML_UTF8 = "<?xml version='1.0' encoding='UTF-8'?>"; //$NON-NLS-1$

		public ProcessingInstruction(String target, String[] attrs, String[] values) {
			// Lengths of attributes and values must be the same
			this.target = target;
			this.data = new String[attrs.length];
			for (int i = 0; i < attrs.length; i++) {
				data[i] = attributeImage(attrs[i], values[i]);
			}
		}

		public static ProcessingInstruction makeTargetVersionInstruction(String target, Version version) {
			return new ProcessingInstruction(target, new String[] {PI_VERSION_ATTRIBUTE}, new String[] {version.toString()});
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder("<?"); //$NON-NLS-1$
			sb.append(this.target).append(' ');
			for (int i = 0; i < data.length; i++) {
				sb.append(this.data[i]);
				if (i < data.length - 1) {
					sb.append(' ');
				}
			}
			sb.append("?>"); //$NON-NLS-1$
			return sb.toString();
		}
	}

	private Stack<String> elements; // XML elements that have not yet been closed
	private boolean open; // Can attributes be added to the current element?
	private String indent; // used for each level of indentation

	private PrintWriter pw;

	public XMLWriter(OutputStream output, ProcessingInstruction[] piElements) {
		this.pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)), false);
		println(ProcessingInstruction.XML_UTF8);
		this.elements = new Stack<>();
		this.open = false;
		this.indent = "  "; //$NON-NLS-1$
		if (piElements != null) {
			for (ProcessingInstruction piElement : piElements) {
				println(piElement.toString());
			}
		}
	}

	// start a new element
	public void start(String name) {
		if (this.open) {
			println('>');
		}
		indent();
		print('<');
		print(name);
		this.elements.push(name);
		this.open = true;
	}

	// end the most recent element with this name
	public void end(String name) {
		if (this.elements.empty()) {
			throw new EndWithoutStartError();
		}
		int index = this.elements.search(name);
		if (index == -1) {
			throw new EndWithoutStartError(name);
		}
		for (int i = 0; i < index; i += 1) {
			end();
		}
	}

	// end the current element
	public void end() {
		if (this.elements.empty()) {
			throw new EndWithoutStartError();
		}
		String name = this.elements.pop();
		if (this.open) {
			println("/>"); //$NON-NLS-1$
		} else {
			printlnIndented("</" + name + '>', false); //$NON-NLS-1$
		}
		this.open = false;
	}

	public static String escape(String txt) {
		StringBuffer buffer = null;
		for (int i = 0; i < txt.length(); ++i) {
			String replace;
			char c = txt.charAt(i);
			switch (c) {
				case '<' :
					replace = "&lt;"; //$NON-NLS-1$
					break;
				case '>' :
					replace = "&gt;"; //$NON-NLS-1$
					break;
				case '"' :
					replace = "&quot;"; //$NON-NLS-1$
					break;
				case '\'' :
					replace = "&apos;"; //$NON-NLS-1$
					break;
				case '&' :
					replace = "&amp;"; //$NON-NLS-1$
					break;
				case '\t' :
					replace = "&#x9;"; //$NON-NLS-1$
					break;
				case '\n' :
					replace = "&#xA;"; //$NON-NLS-1$
					break;
				case '\r' :
					replace = "&#xD;"; //$NON-NLS-1$
					break;
				default :
					// this is the set of legal xml scharacters in unicode excluding high surrogates since they cannot be represented with a char
					// see http://www.w3.org/TR/REC-xml/#charsets
					if ((c >= '\u0020' && c <= '\uD7FF') || (c >= '\uE000' && c <= '\uFFFD')) {
						if (buffer != null)
							buffer.append(c);
						continue;
					}
					replace = Character.isWhitespace(c) ? " " : null; //$NON-NLS-1$
			}
			if (buffer == null) {
				buffer = new StringBuffer(txt.length() + 16);
				buffer.append(txt.substring(0, i));
			}
			if (replace != null)
				buffer.append(replace);
		}

		if (buffer == null)
			return txt;

		return buffer.toString();
	}

	// write a boolean attribute if it doesn't have the default value
	public void attribute(String name, boolean value, boolean defaultValue) {
		if (value != defaultValue) {
			attribute(name, value);
		}
	}

	public void attribute(String name, boolean value) {
		attribute(name, Boolean.toString(value));
	}

	public void attribute(String name, int value) {
		attribute(name, Integer.toString(value));
	}

	public void attributeOptional(String name, String value) {
		if (value != null && value.length() > 0) {
			attribute(name, value);
		}
	}

	public void attribute(String name, Object value) {
		if (!this.open) {
			throw new AttributeAfterNestedContentError();
		}
		if (value == null) {
			return; // optional attribute with no value
		}
		print(' ');
		print(name);
		print("='"); //$NON-NLS-1$
		print(escape(value.toString()));
		print('\'');
	}

	public void cdata(String data) {
		cdata(data, true);
	}

	public void cdata(String data, boolean escape) {
		if (this.open) {
			println('>');
			this.open = false;
		}
		if (data != null) {
			printlnIndented(data, escape);
		}
	}

	public void flush() {
		this.pw.flush();
	}

	public void writeProperties(Map<String, ?> properties) {
		writeProperties(PROPERTIES_ELEMENT, properties);
	}

	public void writeProperties(String propertiesElement, Map<String, ?> properties) {
		if (properties == null || properties.isEmpty()) {
			return;
		}

		start(propertiesElement);
		attribute(COLLECTION_SIZE_ATTRIBUTE, properties.size());
		properties.forEach(this::writeProperty);
		end();
	}

	public void writeProperty(String name, Object value) {
		String type;
		String valueStr;

		if (Collection.class.isAssignableFrom(value.getClass())) {
			Collection<?> coll = (Collection<?>) value;

			type = PROPERTY_TYPE_LIST;
			String elType = resolvePropertyType(coll.iterator().next());
			if (elType != null) {
				type += String.format("<%s>", elType); //$NON-NLS-1$
			}

			valueStr = coll.stream().map(Object::toString).collect(joining(",")); //$NON-NLS-1$
		} else {
			type = resolvePropertyType(value);
			valueStr = value.toString();
		}

		start(PROPERTY_ELEMENT);
		attribute(PROPERTY_NAME_ATTRIBUTE, name);
		attribute(PROPERTY_VALUE_ATTRIBUTE, valueStr);
		attributeOptional(PROPERTY_TYPE_ATTRIBUTE, type);
		end();
	}

	private String resolvePropertyType(Object value) {
		if (value instanceof Integer) {
			return PROPERTY_TYPE_INTEGER;
		}
		if (value instanceof Long) {
			return PROPERTY_TYPE_LONG;
		}
		if (value instanceof Float) {
			return PROPERTY_TYPE_FLOAT;
		}
		if (value instanceof Double) {
			return PROPERTY_TYPE_DOUBLE;
		}
		if (value instanceof Byte) {
			return PROPERTY_TYPE_BYTE;
		}
		if (value instanceof Short) {
			return PROPERTY_TYPE_SHORT;
		}
		if (value instanceof Character) {
			return PROPERTY_TYPE_CHARACTER;
		}
		if (value instanceof Boolean) {
			return PROPERTY_TYPE_BOOLEAN;
		}
		if (value instanceof Version) {
			return PROPERTY_TYPE_VERSION;
		}

		// Null is read back as String
		// NOTE: Using string as default is needed for backward compatibility with properties that are always String like
		// the IU properties
		return null;
	}

	protected static String attributeImage(String name, String value) {
		if (value == null) {
			return ""; // optional attribute with no value //$NON-NLS-1$
		}
		return name + "='" + escape(value) + '\''; //$NON-NLS-1$
	}

	private void println(char c) {
		this.pw.println(c);
	}

	private void println(String s) {
		this.pw.println(s);
	}

	private void println() {
		this.pw.println();
	}

	private void print(char c) {
		this.pw.print(c);
	}

	private void print(String s) {
		this.pw.print(s);
	}

	private void printlnIndented(String s, boolean escape) {
		if (s.length() == 0) {
			println();
		} else {
			indent();
			println(escape ? escape(s) : s);
		}
	}

	private void indent() {
		for (int i = this.elements.size(); i > 0; i -= 1) {
			print(this.indent);
		}
	}

	public static class AttributeAfterNestedContentError extends Error {
		private static final long serialVersionUID = 1L; // not serialized
	}

	public static class EndWithoutStartError extends Error {
		private static final long serialVersionUID = 1L; // not serialized
		private String name;

		public EndWithoutStartError() {
			super();
		}

		public EndWithoutStartError(String name) {
			super();
			this.name = name;
		}

		public String getName() {
			return this.name;
		}
	}

}
