package org.bouncycastle.pqc.jcajce.provider.rainbow;

import java.io.IOException;
import java.security.PrivateKey;
import java.util.Arrays;

import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers;
import org.bouncycastle.pqc.asn1.RainbowPrivateKey;
import org.bouncycastle.pqc.crypto.rainbow.Layer;
import org.bouncycastle.pqc.crypto.rainbow.RainbowPrivateKeyParameters;
import org.bouncycastle.pqc.crypto.rainbow.util.RainbowUtil;
import org.bouncycastle.pqc.jcajce.spec.RainbowPrivateKeySpec;

/**
 * The Private key in Rainbow consists of the linear affine maps L1, L2 and the
 * map F, consisting of quadratic polynomials. In this implementation, we
 * denote: L1 = A1*x + b1 L2 = A2*x + b2
 * <p>
 * The coefficients of the polynomials in F are stored in 3-dimensional arrays
 * per layer. The indices of these arrays denote the polynomial, and the
 * variables.
 * </p><p>
 * More detailed information about the private key is to be found in the paper
 * of Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable Polynomial
 * Signature Scheme. ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12)
 * </p>
 */
public class BCRainbowPrivateKey
    implements PrivateKey
{
    private static final long serialVersionUID = 1L;

    // the inverse of L1
    private short[][] A1inv;

    // translation vector element of L1
    private short[] b1;

    // the inverse of L2
    private short[][] A2inv;

    // translation vector of L2
    private short[] b2;

    /*
      * components of F
      */
    private Layer[] layers;

    // set of vinegar vars per layer.
    private int[] vi;


    /**
     * Constructor.
     *
     * @param A1inv
     * @param b1
     * @param A2inv
     * @param b2
     * @param layers
     */
    public BCRainbowPrivateKey(short[][] A1inv, short[] b1, short[][] A2inv,
                               short[] b2, int[] vi, Layer[] layers)
    {
        this.A1inv = A1inv;
        this.b1 = b1;
        this.A2inv = A2inv;
        this.b2 = b2;
        this.vi = vi;
        this.layers = layers;
    }

    /**
     * Constructor (used by the {@link RainbowKeyFactorySpi}).
     *
     * @param keySpec a {@link RainbowPrivateKeySpec}
     */
    public BCRainbowPrivateKey(RainbowPrivateKeySpec keySpec)
    {
        this(keySpec.getInvA1(), keySpec.getB1(), keySpec.getInvA2(), keySpec
            .getB2(), keySpec.getVi(), keySpec.getLayers());
    }

    public BCRainbowPrivateKey(
        RainbowPrivateKeyParameters params)
    {
        this(params.getInvA1(), params.getB1(), params.getInvA2(), params.getB2(), params.getVi(), params.getLayers());
    }

    /**
     * Getter for the inverse matrix of A1.
     *
     * @return the A1inv inverse
     */
    public short[][] getInvA1()
    {
        return this.A1inv;
    }

    /**
     * Getter for the translation part of the private quadratic map L1.
     *
     * @return b1 the translation part of L1
     */
    public short[] getB1()
    {
        return this.b1;
    }

    /**
     * Getter for the translation part of the private quadratic map L2.
     *
     * @return b2 the translation part of L2
     */
    public short[] getB2()
    {
        return this.b2;
    }

    /**
     * Getter for the inverse matrix of A2
     *
     * @return the A2inv
     */
    public short[][] getInvA2()
    {
        return this.A2inv;
    }

    /**
     * Returns the layers contained in the private key
     *
     * @return layers
     */
    public Layer[] getLayers()
    {
        return this.layers;
    }

    /**
     * Returns the array of vi-s
     *
     * @return the vi
     */
    public int[] getVi()
    {
        return vi;
    }

    /**
     * Compare this Rainbow private key with another object.
     *
     * @param other the other object
     * @return the result of the comparison
     */
    public boolean equals(Object other)
    {
        if (other == null || !(other instanceof BCRainbowPrivateKey))
        {
            return false;
        }
        BCRainbowPrivateKey otherKey = (BCRainbowPrivateKey)other;

        boolean eq = true;
        // compare using shortcut rule ( && instead of &)
        eq = eq && RainbowUtil.equals(A1inv, otherKey.getInvA1());
        eq = eq && RainbowUtil.equals(A2inv, otherKey.getInvA2());
        eq = eq && RainbowUtil.equals(b1, otherKey.getB1());
        eq = eq && RainbowUtil.equals(b2, otherKey.getB2());
        eq = eq && Arrays.equals(vi, otherKey.getVi());
        if (layers.length != otherKey.getLayers().length)
        {
            return false;
        }
        for (int i = layers.length - 1; i >= 0; i--)
        {
            eq &= layers[i].equals(otherKey.getLayers()[i]);
        }
        return eq;
    }

    public int hashCode()
    {
        int hash = layers.length;

        hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(A1inv);
        hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(b1);
        hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(A2inv);
        hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(b2);
        hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(vi);

        for (int i = layers.length - 1; i >= 0; i--)
        {
            hash = hash * 37 + layers[i].hashCode();
        }


        return hash;
    }

    /**
     * @return name of the algorithm - "Rainbow"
     */
    public final String getAlgorithm()
    {
        return "Rainbow";
    }

    public byte[] getEncoded()
    {
        RainbowPrivateKey privateKey = new RainbowPrivateKey(A1inv, b1, A2inv, b2, vi, layers);

        PrivateKeyInfo pki;
        try
        {
            AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.rainbow, DERNull.INSTANCE);
            pki = new PrivateKeyInfo(algorithmIdentifier, privateKey);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
        try
        {
            byte[] encoded = pki.getEncoded();
            return encoded;
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    public String getFormat()
    {
        return "PKCS#8";
    }
}
