package org.codiki.core.entities.security;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Calendar;

public class Token {
	/** The metric in which the validation delay is defined. */
	private static final int METRIC = Calendar.MINUTE;
	/** Number of {@link METRIC} after that the token become invalid. */
	private static final int DELAY = 30;
	
	/** The Constant BITS_NUMBER. */
	private static final int BITS_NUMBER = 1000;
	/** The Constant RADIX. */
	private static final int RADIX = 32;
	
	/** The value. */
	private String value;
	
	/**
	 * Last access date. For each request to the server, this date is consulted
	 * and if the valid delay is ok, this date must be updated.
	 */
	private Calendar lastAccess;
	
	/**
	 * Instantiates a new token.
	 */
	public Token() {
		super();
		value = new BigInteger(BITS_NUMBER, new SecureRandom()).toString(RADIX);
		lastAccess = Calendar.getInstance();
	}

	/**
	 * Gets the value.
	 *
	 * @return the value
	 */
	public String getValue() {
		return value;
	}

	/**
	 * Gets the last access date.
	 *
	 * @return the last access date
	 */
	public Calendar getLastAccess() {
		return lastAccess;
	}

	/**
	 * Sets the last access date.
	 */
	public void setLastAccess() {
		lastAccess = Calendar.getInstance();
	}
	
	/**
	 * Indicate if the token is still valid.<br/>
	 * A token is valid is its {@link Token#lastAccess} is after the current
	 * date minus the {@link Token#DELAY} {@link Token#METRIC}.<br/>
	 * <br/>
	 * Example:<br/>
	 * {@link Token#DELAY} = 30 and {@link Token#METRIC} =
	 * {@link Calendar#MINUTE}.<br/>
	 * A token is valid only on the 30 minutes after its
	 * {@link Token#lastAccess}.<br/>
	 * If the current date-time minus the 30 minutes is before the
	 * {@link Token#lastAccess}, the token is still valid.
	 * 
	 * @return {@code true} if the token is still valid, {@code false}
	 *         otherwise.
	 */
	public boolean isValid() {
		final Calendar lastTimeValidation = Calendar.getInstance();
		lastTimeValidation.add(METRIC, -DELAY);
		return lastAccess.getTime().after(lastTimeValidation.getTime());
	}
}
