package com.njzscloud.common.core.tuple;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 2 元组
 *
 * @param <_0>
 * @param <_1>
 */
public class Tuple2<_0, _1> {

    /**
     * 元组大小
     */
    @JsonIgnore
    public final int size = 2;
    /**
     * 第 0 个数据
     */
    @JsonIgnore
    protected final _0 _0_;
    /**
     * 第 1 个数据
     */
    @JsonIgnore
    protected final _1 _1_;

    /**
     * 构造方法
     *
     * @param _0_ 第 0 个数据
     * @param _1_ 第 1 个数据
     */
    public Tuple2(_0 _0_, _1 _1_) {
        this._0_ = _0_;
        this._1_ = _1_;
    }

    /**
     * 创建 Tuple2
     *
     * @param _0_ 第 0 个数据
     * @param _1_ 第 1 个数据
     * @return Tuple2&lt;__0, __1&gt;
     */
    public static <__0, __1> Tuple2<__0, __1> of(__0 _0_, __1 _1_) {
        return new Tuple2<>(_0_, _1_);
    }

    /**
     * 获取第 0 个数据
     */
    @JsonProperty("0")
    public _0 get_0() {
        return _0_;
    }

    /**
     * 获取第 1 个数据
     */
    @JsonProperty("1")
    public _1 get_1() {
        return _1_;
    }

    /**
     * <p>按索引获取数据</p>
     * <p>索引越界将返回 null</p>
     *
     * @param index 索引
     * @return T
     */
    @SuppressWarnings("unchecked")
    public <T> T get(int index) {
        return switch (index) {
            case 0 -> (T) this._0_;
            case 1 -> (T) this._1_;
            default -> null;
        };
    }

    /**
     * 转换成 List
     *
     * @return List&lt;Object&gt;
     */
    public List<Object> toList() {
        return Arrays.asList(this.toArray());
    }

    /**
     * 转换成 数组
     *
     * @return Object[]
     */
    public Object[] toArray() {
        return new Object[]{this._0_, this._1_};
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Tuple2<?, ?> tuple2 = (Tuple2<?, ?>) o;
        return Objects.equals(_0_, tuple2._0_) && Objects.equals(_1_, tuple2._1_);
    }

    @Override
    public int hashCode() {
        return Objects.hash(_0_, _1_);
    }
}
