/**

* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/

package net.i2p.crypto.eddsa.math;

import java.io.Serializable;

/**

* A twisted Edwards curve.
* Points on the curve satisfy $-x^2 + y^2 = 1 + d x^2y^2$
* @author str4d
*
*/

public class Curve implements Serializable {

private static final long serialVersionUID = 4578920872509827L;
private final Field f;
private final FieldElement d;
private final FieldElement d2;
private final FieldElement I;

private final GroupElement zeroP2;
private final GroupElement zeroP3;
private final GroupElement zeroPrecomp;

public Curve(Field f, byte[] d, FieldElement I) {
    this.f = f;
    this.d = f.fromByteArray(d);
    this.d2 = this.d.add(this.d);
    this.I = I;

    FieldElement zero = f.ZERO;
    FieldElement one = f.ONE;
    zeroP2 = GroupElement.p2(this, zero, one, one);
    zeroP3 = GroupElement.p3(this, zero, one, one, zero);
    zeroPrecomp = GroupElement.precomp(this, one, one, zero);
}

public Field getField() {
    return f;
}

public FieldElement getD() {
    return d;
}

public FieldElement get2D() {
    return d2;
}

public FieldElement getI() {
    return I;
}

public GroupElement getZero(GroupElement.Representation repr) {
    switch (repr) {
    case P2:
        return zeroP2;
    case P3:
        return zeroP3;
    case PRECOMP:
        return zeroPrecomp;
    default:
        return null;
    }
}

public GroupElement createPoint(byte[] P, boolean precompute) {
    GroupElement ge = new GroupElement(this, P);
    if (precompute)
        ge.precompute(true);
    return ge;
}

@Override
public int hashCode() {
    return f.hashCode() ^
           d.hashCode() ^
           I.hashCode();
}

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof Curve))
        return false;
    Curve c = (Curve) o;
    return f.equals(c.getField()) &&
           d.equals(c.getD()) &&
           I.equals(c.getI());
}

}