/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Mickael Istria (Red Hat Inc.) - Bug 488938, 488937
 *******************************************************************************/
package org.eclipse.core.internal.utils;

import java.io.*;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.GregorianCalendar;
import java.util.Random;

public class UniversalUniqueIdentifier implements java.io.Serializable {

	/**
	 * All serializable objects should have a stable serialVersionUID
	 */
	private static final long serialVersionUID = 1L;

	/* INSTANCE FIELDS =============================================== */

	private byte[] fBits = new byte[BYTES_SIZE];

	/* NON-FINAL PRIVATE STATIC FIELDS =============================== */

	private static BigInteger fgPreviousClockValue;
	private static int fgClockAdjustment = 0;
	private static int fgClockSequence = -1;
	private static byte[] nodeAddress;

	static {
		nodeAddress = computeNodeAddress();
	}

	/* PRIVATE STATIC FINAL FIELDS =================================== */

	private static Random fgRandomNumberGenerator = new Random();

	/* PUBLIC STATIC FINAL FIELDS ==================================== */

	public static final int BYTES_SIZE = 16;
	public static final byte[] UNDEFINED_UUID_BYTES = new byte[16];
	public static final int MAX_CLOCK_SEQUENCE = 0x4000;
	public static final int MAX_CLOCK_ADJUSTMENT = 0x7FFF;
	public static final int TIME_FIELD_START = 0;
	public static final int TIME_FIELD_STOP = 6;
	public static final int TIME_HIGH_AND_VERSION = 7;
	public static final int CLOCK_SEQUENCE_HIGH_AND_RESERVED = 8;
	public static final int CLOCK_SEQUENCE_LOW = 9;
	public static final int NODE_ADDRESS_START = 10;
	public static final int NODE_ADDRESS_BYTE_SIZE = 6;

	public static final int BYTE_MASK = 0xFF;

	public static final int HIGH_NIBBLE_MASK = 0xF0;

	public static final int LOW_NIBBLE_MASK = 0x0F;

	public static final int SHIFT_NIBBLE = 4;

	public static final int ShiftByte = 8;

	/**
	 UniversalUniqueIdentifier default constructor returns a
	 new instance that has been initialized to a unique value.
	 */
	public UniversalUniqueIdentifier() {
		this.setVersion(1);
		this.setVariant(1);
		this.setTimeValues();
		this.setNode(getNodeAddress());
	}

	/**
	 Constructor that accepts the bytes to use for the instance.&nbsp;&nbsp; The format
	 of the byte array is compatible with the <code>toBytes()</code> method.
	
	 <p>The constructor returns the undefined uuid if the byte array is invalid.
	
	 @see #toBytes()
	 @see #BYTES_SIZE
	 */
	public UniversalUniqueIdentifier(byte[] byteValue) {
		fBits = new byte[BYTES_SIZE];
		if (byteValue.length >= BYTES_SIZE)
			System.arraycopy(byteValue, 0, fBits, 0, BYTES_SIZE);
	}

	private void appendByteString(StringBuilder buffer, byte value) {
		String hexString;

		if (value < 0)
			hexString = Integer.toHexString(256 + value);
		else
			hexString = Integer.toHexString(value);
		if (hexString.length() == 1)
			buffer.append("0"); //$NON-NLS-1$
		buffer.append(hexString);
	}

	private static BigInteger clockValueNow() {
		GregorianCalendar now = new GregorianCalendar();
		BigInteger nowMillis = BigInteger.valueOf(now.getTime().getTime());
		BigInteger baseMillis = BigInteger.valueOf(now.getGregorianChange().getTime());

		return (nowMillis.subtract(baseMillis).multiply(BigInteger.valueOf(10000L)));
	}

	public static int compareTime(byte[] fBits1, byte[] fBits2) {
		for (int i = TIME_FIELD_STOP; i >= 0; i--)
			if (fBits1[i] != fBits2[i])
				return (0xFF & fBits1[i]) - (0xFF & fBits2[i]);
		return 0;
	}

	/**
	 * Answers the node address attempting to mask the IP
	 * address of this machine.
	 *
	 * @return byte[] the node address
	 */
	private static byte[] computeNodeAddress() {

		byte[] address = new byte[NODE_ADDRESS_BYTE_SIZE];

		// Seed the secure randomizer with some oft-varying inputs
		int thread = Thread.currentThread().hashCode();
		long time = System.currentTimeMillis();
		int objectId = System.identityHashCode(""); //$NON-NLS-1$
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		DataOutputStream out = new DataOutputStream(byteOut);
		byte[] ipAddress = getIPAddress();

		try {
			if (ipAddress != null)
				out.write(ipAddress);
			out.write(thread);
			out.writeLong(time);
			out.write(objectId);
			out.close();
		} catch (IOException exc) {
			//ignore the failure, we're just trying to come up with a random seed
		}
		byte[] rand = byteOut.toByteArray();

		SecureRandom randomizer = new SecureRandom(rand);
		randomizer.nextBytes(address);

		// set the MSB of the first octet to 1 to distinguish from IEEE node addresses
		address[0] = (byte) (address[0] | (byte) 0x80);

		return address;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!(obj instanceof UniversalUniqueIdentifier))
			return false;

		byte[] other = ((UniversalUniqueIdentifier) obj).fBits;
		if (fBits == other)
			return true;
		if (fBits.length != other.length)
			return false;
		for (int i = 0; i < fBits.length; i++) {
			if (fBits[i] != other[i])
				return false;
		}
		return true;
	}

	/**
	 Answers the IP address of the local machine using the
	 Java API class <code>InetAddress</code>.
	
	 @return byte[] the network address in network order
	 @see    java.net.InetAddress#getLocalHost()
	 @see    java.net.InetAddress#getAddress()
	 */
	protected static byte[] getIPAddress() {
		try {
			return InetAddress.getLocalHost().getAddress();
		} catch (UnknownHostException e) {
			//valid for this to be thrown be a machine with no IP connection
			//It is VERY important NOT to throw this exception
			return null;
		} catch (ArrayIndexOutOfBoundsException e) {
			// there appears to be a bug in the VM if there is an alias
			// see bug 354820. As above it is important not to throw this
			return null;
		}
	}

	private static byte[] getNodeAddress() {
		return nodeAddress;
	}

	@Override
	public int hashCode() {
		return fBits[0] + fBits[3] + fBits[7] + fBits[11] + fBits[15];
	}

	private static int nextClockSequence() {

		if (fgClockSequence == -1)
			fgClockSequence = (int) (fgRandomNumberGenerator.nextDouble() * MAX_CLOCK_SEQUENCE);

		fgClockSequence = (fgClockSequence + 1) % MAX_CLOCK_SEQUENCE;

		return fgClockSequence;
	}

	private static BigInteger nextTimestamp() {

		BigInteger timestamp = clockValueNow();
		int timestampComparison;

		timestampComparison = timestamp.compareTo(fgPreviousClockValue);

		if (timestampComparison == 0) {
			if (fgClockAdjustment == MAX_CLOCK_ADJUSTMENT) {
				while (timestamp.compareTo(fgPreviousClockValue) == 0)
					timestamp = clockValueNow();
				timestamp = nextTimestamp();
			} else
				fgClockAdjustment++;
		} else {
			fgClockAdjustment = 0;

			if (timestampComparison < 0)
				nextClockSequence();
		}

		return timestamp;
	}

	private void setClockSequence(int clockSeq) {
		int clockSeqHigh = (clockSeq >>> ShiftByte) & LOW_NIBBLE_MASK;
		int reserved = fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] & HIGH_NIBBLE_MASK;

		fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] = (byte) (reserved | clockSeqHigh);
		fBits[CLOCK_SEQUENCE_LOW] = (byte) (clockSeq & BYTE_MASK);
	}

	protected void setNode(byte[] bytes) {

		for (int index = 0; index < NODE_ADDRESS_BYTE_SIZE; index++)
			fBits[index + NODE_ADDRESS_START] = bytes[index];
	}

	private void setTimestamp(BigInteger timestamp) {
		BigInteger value = timestamp;
		BigInteger bigByte = BigInteger.valueOf(256L);
		BigInteger[] results;
		int version;
		int timeHigh;

		for (int index = TIME_FIELD_START; index < TIME_FIELD_STOP; index++) {
			results = value.divideAndRemainder(bigByte);
			value = results[0];
			fBits[index] = (byte) results[1].intValue();
		}
		version = fBits[TIME_HIGH_AND_VERSION] & HIGH_NIBBLE_MASK;
		timeHigh = value.intValue() & LOW_NIBBLE_MASK;
		fBits[TIME_HIGH_AND_VERSION] = (byte) (timeHigh | version);
	}

	protected synchronized void setTimeValues() {
		this.setTimestamp(timestamp());
		this.setClockSequence(fgClockSequence);
	}

	protected int setVariant(int variantIdentifier) {
		int clockSeqHigh = fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] & LOW_NIBBLE_MASK;
		int variant = variantIdentifier & LOW_NIBBLE_MASK;

		fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] = (byte) ((variant << SHIFT_NIBBLE) | clockSeqHigh);
		return (variant);
	}

	protected void setVersion(int versionIdentifier) {
		int timeHigh = fBits[TIME_HIGH_AND_VERSION] & LOW_NIBBLE_MASK;
		int version = versionIdentifier & LOW_NIBBLE_MASK;

		fBits[TIME_HIGH_AND_VERSION] = (byte) (timeHigh | (version << SHIFT_NIBBLE));
	}

	private static BigInteger timestamp() {
		BigInteger timestamp;

		if (fgPreviousClockValue == null) {
			fgClockAdjustment = 0;
			nextClockSequence();
			timestamp = clockValueNow();
		} else
			timestamp = nextTimestamp();

		fgPreviousClockValue = timestamp;
		return fgClockAdjustment == 0 ? timestamp : timestamp.add(BigInteger.valueOf(fgClockAdjustment));
	}

	/**
	 This representation is compatible with the (byte[]) constructor.
	
	 @see #UniversalUniqueIdentifier(byte[])
	 */
	public byte[] toBytes() {
		byte[] result = new byte[fBits.length];

		System.arraycopy(fBits, 0, result, 0, fBits.length);
		return result;
	}

	@Override
	public String toString() {
		StringBuilder buffer = new StringBuilder();
		for (byte bit : fBits)
			appendByteString(buffer, bit);
		return buffer.toString();
	}

	public String toStringAsBytes() {
		StringBuilder result = new StringBuilder("{"); //$NON-NLS-1$

		for (int i = 0; i < fBits.length; i++) {
			result.append(fBits[i]);
			if (i < fBits.length + 1)
				result.append(',');
		}
		result.append('}');
		return result.toString();
	}
}
