/*
 * Copyright 2011 Federal Chancellery Austria and
 * Graz University of Technology
 * 
 * Licensed 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 at.gv.util;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
 */
public final class ToStringUtil {

	public static final String DEFAULT_NULL = "null";
	public static final String DEFAULT_AROUND = "";
	public static final String DEFAULT_DELIMITER = ", ";

	private ToStringUtil() {
	}

	// implementing methods

	public static <E> String toString(Enum enumImpl) {
		return enumImpl == null ? DEFAULT_NULL : enumImpl.name();
	}

	public static String toString(Throwable t) {
		ByteArrayOutputStream baout = new ByteArrayOutputStream();
		t.printStackTrace(new PrintStream(baout, true));
		String result = new String(baout.toByteArray());
		return result;
	}

	public static String toString(byte b) {
		StringBuffer sb = new StringBuffer(2);
		int h = (b & 0xf0) >> 4;
		int l = (b & 0x0f);
		sb.append(new Character((char) ((h > 9) ? 'a' + h - 10 : '0' + h)));
		sb.append(new Character((char) ((l > 9) ? 'a' + l - 10 : '0' + l)));
		return sb.toString();
	}

	public static String toString(byte[] data, String delimiter,
	    boolean removeLeadingZeros) {
		StringBuffer result = new StringBuffer();
		int i = 0;
		if (removeLeadingZeros) {
			for (; i < data.length && data[i] == 0; i++)
				;
		}
		for (; i < data.length; i++) {
			result.append(toString(data[i]));
			if (delimiter != null && (i + 1) < data.length) {
				result.append(delimiter);
			}
		}
		if (result.length() == 0 && data.length > 0) {
			result.append("00");
		}
		return result.toString();
	}

	public static String toString(byte[] data, String delimiter) {
		return toString(data, delimiter, false);
	}

	public static String toString(byte[] data) {
		return toString(data, null);
	}

	public static String toString(Object a) {
		if (a == null) {
			return DEFAULT_NULL;
		}

		if (a instanceof Enum) {
			return toString((Enum) a);

		} else {
			return a.toString();
		}
	}

	// some convenient functions

	public static <T> String[] toStringArray(T[] a) {
		if (a == null) {
			return null;
		}
		String[] result = new String[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = toString(a[i]);
		}
		return result;
	}

	public static <T> String toString(T[] a) {
		return toString(a, DEFAULT_DELIMITER);
	}

	public static <T> String toString(T[] a, String delimiter) {
		return toString(a, delimiter, DEFAULT_AROUND);
	}

	public static <T> String toString(T[] a, String delimiter, String around) {
		return toString(Arrays.asList(a), delimiter, around);
	}

	public static <T> String toString(Iterable<T> iterable) {
		return toString(iterable, DEFAULT_DELIMITER);
	}

	public static <T> String toString(Iterable<T> iterable, String delimiter) {
		return toString(iterable, delimiter, DEFAULT_AROUND);
	}

	public static <T> String toString(Iterable<T> iterable, String delimiter,
	    String around) {
		if (iterable == null) {
			return DEFAULT_NULL;
		}
		StringBuffer buffer = new StringBuffer();
		Iterator<T> it = iterable.iterator();
		while (it.hasNext()) {
			T next = it.next();
			buffer.append(around).append(toString(next)).append(around);
			if (it.hasNext()) {
				buffer.append(delimiter);
			}
		}
		return buffer.toString();
	}

	public static <T> String toString(Enumeration<T> enumeration) {
		return toString(enumeration, DEFAULT_DELIMITER);
	}

	public static <T> String toString(Enumeration<T> enumeration, String delimiter) {
		return toString(enumeration, delimiter, DEFAULT_AROUND);
	}

	public static <T> String toString(Enumeration<T> enumeration,
	    String delimiter, String around) {
		if (enumeration == null) {
			return DEFAULT_NULL;
		}
		StringBuffer buffer = new StringBuffer();
		while (enumeration.hasMoreElements()) {
			T next = enumeration.nextElement();
			buffer.append(around).append(toString(next)).append(around);
			if (enumeration.hasMoreElements()) {
				buffer.append(delimiter);
			}
		}
		return buffer.toString();
	}

	public static String toString(NamedNodeMap nnm) {
		ToStringBuilder tsb = new ToStringBuilder(nnm);
		for (int i = 0; i < nnm.getLength(); i++) {
			Node node = nnm.item(i);
			tsb.append(node.getNodeName(), node.getNodeValue());
		}
		return tsb.toString();
	}

}