package cz.senslog.connector.tools.util;

import java.util.Objects;

/**
 * The class {@code Triple} represents an accumulator for three values.
 * Each value can be in different type.
 *
 * @param <A> type of the first value.
 * @param <B> type of the second value.
 * @param <C> type of the third value.
 *
 * @author Lukas Cerny
 * @version 1.0
 * @since 1.0
 */
public class Triple<A, B, C> {

    /** First value. */
    private final A item1;

    /** Second value. */
    private final B item2;

    /** Third value. */
    private final C item3;

    /**
     * Factory method to create a new instance.
     * @param item1 first value.
     * @param item2 second value.
     * @param item3 third value.
     * @param <A> type of the first value.
     * @param <B> type of the second value.
     * @param <C> type of the third value.
     * @return new instance of {@code Triple}.
     */
    public static <A, B, C> Triple<A, B, C> of(A item1, B item2, C item3) {
        return new Triple<>(item1, item2, item3);
    }

    /**
     * Constructor of the class sets all attributes.
     * @param item1 first value.
     * @param item2 second value.
     * @param item3 third value.
     */
    private Triple(A item1, B item2, C item3) {
        this.item1 = item1;
        this.item2 = item2;
        this.item3 = item3;
    }

    public A getItem1() {
        return item1;
    }

    public B getItem2() {
        return item2;
    }

    public C getItem3() {
        return item3;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Triple<?, ?, ?> triple = (Triple<?, ?, ?>) o;
        return item1.equals(triple.item1) &&
                item2.equals(triple.item2) &&
                item3.equals(triple.item3);
    }

    @Override
    public int hashCode() {
        return Objects.hash(item1, item2, item3);
    }
}
