package org.bouncycastle.math.ec.custom.sec;

import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.ECPoint.AbstractF2m;

public class SecT283K1Point extends AbstractF2m
{
    /**
     * @deprecated Use ECCurve.createPoint to construct points
     */
    public SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
    {
        this(curve, x, y, false);
    }

    /**
     * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
     */
    public SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
    {
        super(curve, x, y);

        if ((x == null) != (y == null))
        {
            throw new IllegalArgumentException("Exactly one of the field elements is null");
        }

        this.withCompression = withCompression;
    }

    SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
    {
        super(curve, x, y, zs);

        this.withCompression = withCompression;
    }

    protected ECPoint detach()
    {
        return new SecT283K1Point(null, this.getAffineXCoord(), this.getAffineYCoord()); // earlier JDK
    }

    public ECFieldElement getYCoord()
    {
        ECFieldElement X = x, L = y;

        if (this.isInfinity() || X.isZero())
        {
            return L;
        }

        // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
        ECFieldElement Y = L.add(X).multiply(X);

        ECFieldElement Z = zs[0];
        if (!Z.isOne())
        {
            Y = Y.divide(Z);
        }

        return Y;
    }

    protected boolean getCompressionYTilde()
    {
        ECFieldElement X = this.getRawXCoord();
        if (X.isZero())
        {
            return false;
        }

        ECFieldElement Y = this.getRawYCoord();

        // Y is actually Lambda (X + Y/X) here
        return Y.testBitZero() != X.testBitZero();
    }

    public ECPoint add(ECPoint b)
    {
        if (this.isInfinity())
        {
            return b;
        }
        if (b.isInfinity())
        {
            return this;
        }

        ECCurve curve = this.getCurve();

        ECFieldElement X1 = this.x;
        ECFieldElement X2 = b.getRawXCoord();

        if (X1.isZero())
        {
            if (X2.isZero())
            {
                return curve.getInfinity();
            }

            return b.add(this);
        }

        ECFieldElement L1 = this.y, Z1 = this.zs[0];
        ECFieldElement L2 = b.getRawYCoord(), Z2 = b.getZCoord(0);

        boolean Z1IsOne = Z1.isOne();
        ECFieldElement U2 = X2, S2 = L2;
        if (!Z1IsOne)
        {
            U2 = U2.multiply(Z1);
            S2 = S2.multiply(Z1);
        }

        boolean Z2IsOne = Z2.isOne();
        ECFieldElement U1 = X1, S1 = L1;
        if (!Z2IsOne)
        {
            U1 = U1.multiply(Z2);
            S1 = S1.multiply(Z2);
        }

        ECFieldElement A = S1.add(S2);
        ECFieldElement B = U1.add(U2);

        if (B.isZero())
        {
            if (A.isZero())
            {
                return twice();
            }

            return curve.getInfinity();
        }

        ECFieldElement X3, L3, Z3;
        if (X2.isZero())
        {
            // TODO This can probably be optimized quite a bit
            ECPoint p = this.normalize();
            X1 = p.getXCoord();
            ECFieldElement Y1 = p.getYCoord();

            ECFieldElement Y2 = L2;
            ECFieldElement L = Y1.add(Y2).divide(X1);

            X3 = L.square().add(L).add(X1);
            if (X3.isZero())
            {
                return new SecT283K1Point(curve, X3, curve.getB(), this.withCompression);
            }

            ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
            L3 = Y3.divide(X3).add(X3);
            Z3 = curve.fromBigInteger(ECConstants.ONE);
        }
        else
        {
            B = B.square();

            ECFieldElement AU1 = A.multiply(U1);
            ECFieldElement AU2 = A.multiply(U2);

            X3 = AU1.multiply(AU2);
            if (X3.isZero())
            {
                return new SecT283K1Point(curve, X3, curve.getB(), this.withCompression);
            }

            ECFieldElement ABZ2 = A.multiply(B);
            if (!Z2IsOne)
            {
                ABZ2 = ABZ2.multiply(Z2);
            }

            L3 = AU2.add(B).squarePlusProduct(ABZ2, L1.add(Z1));

            Z3 = ABZ2;
            if (!Z1IsOne)
            {
                Z3 = Z3.multiply(Z1);
            }
        }

        return new SecT283K1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
    }

    public ECPoint twice()
    {
        if (this.isInfinity())
        {
            return this;
        }

        ECCurve curve = this.getCurve();

        ECFieldElement X1 = this.x;
        if (X1.isZero())
        {
            // A point with X == 0 is it's own additive inverse
            return curve.getInfinity();
        }


        ECFieldElement L1 = this.y, Z1 = this.zs[0];

        boolean Z1IsOne = Z1.isOne();
        ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
        ECFieldElement T;
        if (Z1IsOne)
        {
            T = L1.square().add(L1);
        }
        else
        {
            T = L1.add(Z1).multiply(L1);
        }

        if (T.isZero())
        {
            return new SecT283K1Point(curve, T, curve.getB(), withCompression);
        }

        ECFieldElement X3 = T.square();
        ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);

        ECFieldElement t1 = L1.add(X1).square();
        ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.square();
        ECFieldElement L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2).add(X3).add(Z3);

        return new SecT283K1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
    }

    public ECPoint twicePlus(ECPoint b)
    {
        if (this.isInfinity())
        {
            return b;
        }
        if (b.isInfinity())
        {
            return twice();
        }

        ECCurve curve = this.getCurve();

        ECFieldElement X1 = this.x;
        if (X1.isZero())
        {
            // A point with X == 0 is it's own additive inverse
            return b;
        }

        // NOTE: twicePlus() only optimized for lambda-affine argument
        ECFieldElement X2 = b.getRawXCoord(), Z2 = b.getZCoord(0);
        if (X2.isZero() || !Z2.isOne())
        {
            return twice().add(b);
        }

        ECFieldElement L1 = this.y, Z1 = this.zs[0];
        ECFieldElement L2 = b.getRawYCoord();

        ECFieldElement X1Sq = X1.square();
        ECFieldElement L1Sq = L1.square();
        ECFieldElement Z1Sq = Z1.square();
        ECFieldElement L1Z1 = L1.multiply(Z1);

        ECFieldElement T = L1Sq.add(L1Z1);
        ECFieldElement L2plus1 = L2.addOne();
        ECFieldElement A = L2plus1.multiply(Z1Sq).add(L1Sq).multiplyPlusProduct(T, X1Sq, Z1Sq);
        ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
        ECFieldElement B = X2Z1Sq.add(T).square();

        if (B.isZero())
        {
            if (A.isZero())
            {
                return b.twice();
            }

            return curve.getInfinity();
        }

        if (A.isZero())
        {
            return new SecT283K1Point(curve, A, curve.getB(), withCompression);
        }

        ECFieldElement X3 = A.square().multiply(X2Z1Sq);
        ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
        ECFieldElement L3 = A.add(B).square().multiplyPlusProduct(T, L2plus1, Z3);

        return new SecT283K1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
    }

    public ECPoint negate()
    {
        if (this.isInfinity())
        {
            return this;
        }

        ECFieldElement X = this.x;
        if (X.isZero())
        {
            return this;
        }

        // L is actually Lambda (X + Y/X) here
        ECFieldElement L = this.y, Z = this.zs[0];
        return new SecT283K1Point(curve, X, L.add(Z), new ECFieldElement[]{ Z }, this.withCompression);
    }
}
