
package com.jayway.awaitility;

import java.util.concurrent.TimeUnit;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

public class Duration {
	
	public static final Duration FOREVER = new Duration();
	public static final Duration ONE_HUNDRED_MILLISECONDS = new Duration(100, MILLISECONDS);
	public static final Duration TWO_HUNDRED_MILLISECONDS = new Duration(200, MILLISECONDS);
	public static final Duration FIVE_HUNDRED_MILLISECONDS = new Duration(500, MILLISECONDS);
	public static final Duration ONE_SECOND = new Duration(1, SECONDS);
	public static final Duration TWO_SECONDS = new Duration(2, SECONDS);
	public static final Duration FIVE_SECONDS = new Duration(5, SECONDS);
	public static final Duration TEN_SECONDS = new Duration(10, SECONDS);
	public static final Duration ONE_MINUTE = new Duration(60, SECONDS);
	public static final Duration TWO_MINUTES = new Duration(120, SECONDS);
	public static final Duration FIVE_MINUTES = new Duration(300, SECONDS);
	public static final Duration TEN_MINUTES = new Duration(600, SECONDS);
	public static final Duration SAME_AS_POLL_INTERVAL = new Duration();
    private static final int NONE = -1;

    private final long value;
	private final TimeUnit unit;

	private Duration() {
		this.value = NONE;
		this.unit = null;
	}

	public Duration(long value, TimeUnit unit) {
		if (value <= 0) {
			throw new IllegalArgumentException("value must be > 0");
		}
		if (unit == null) {
			throw new IllegalArgumentException("TimeUnit cannot be null");
		}
		this.value = value;
		this.unit = unit;
	}

	public TimeUnit getTimeUnit() {
		return unit;
	}

    public String getTimeUnitAsString() {
		return unit == null ? "<not defined>" : unit.toString().toLowerCase();
	}

    public boolean isForever() {
        return unit == null && value == NONE;
    }

	public long getValue() {
		return value;
	}

	public long getValueInMS() {
        if(value == NONE) {
            return value;
        }
		return MILLISECONDS.convert(value, unit);
	}

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Duration duration = (Duration) o;

        return getValueInMS() == duration.getValueInMS();
    }

    @Override
    public int hashCode() {
        int result = (int) (value ^ (value >>> 32));
        result = 31 * result + (unit != null ? unit.hashCode() : 0);
        return result;
    }
}