package de.siphalor.was.util;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;

/**
 * Represents the pair of two values.
 * @param <A> The type of the first value
 * @param <B> The type of the second value
 */
public class Pair<A, B> {
	/**
	 * The first value
	 */
	private final A first;
	/**
	 * The second value
	 */
	private final B second;

	/**
	 * Constructs a new pair.
	 * @param first The first value
	 * @param second The second value
	 * @param <A> The type of the first value
	 * @param <B> The type of the second value
	 * @return The new pair
	 */
	@NotNull
	public static <A, B> Pair<A, B> of(A first, B second) {
		return new Pair<>(first, second);
	}

	/**
	 * Constructs a new pair.
	 * @param first The first value
	 * @param second The second value
	 */
	public Pair(A first, B second) {
		this.first = first;
		this.second = second;
	}

	/**
	 * Gets the first value.
	 * @return The first value
	 */
	public A getFirst() {
		return first;
	}

	/**
	 * Gets the second value.
	 * @return The second value
	 */
	public B getSecond() {
		return second;
	}

	/**
	 * Checks for equality.
	 * @param o The other object
	 * @return Returns whether both are equal
	 */
	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		Pair<?, ?> pair = (Pair<?, ?>) o;
		return Objects.equals(first, pair.first) &&
				Objects.equals(second, pair.second);
	}

	/**
	 * The combined hash code of both values
	 * @return The hash code
	 */
	@Override
	public int hashCode() {
		return Objects.hash(first, second);
	}
}
