package org.bouncycastle.asn1.eac;

import java.math.BigInteger;
import java.util.Enumeration;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.util.Arrays;

/**
 * an Iso7816ECDSAPublicKeyStructure structure.
 * <pre>
 *  Certificate Holder Authorization ::= SEQUENCE {
 *      ASN1TaggedObject primeModulusP;        // OPTIONAL
 *      ASN1TaggedObject firstCoefA;            // OPTIONAL
 *      ASN1TaggedObject secondCoefB;        // OPTIONAL
 *      ASN1TaggedObject basePointG;            // OPTIONAL
 *      ASN1TaggedObject orderOfBasePointR;    // OPTIONAL
 *      ASN1TaggedObject publicPointY;        //REQUIRED
 *      ASN1TaggedObject    cofactorF;            // OPTIONAL
 *  }
 * </pre>
 */
public class ECDSAPublicKey
    extends PublicKeyDataObject
{
    private ASN1ObjectIdentifier usage;
    private BigInteger primeModulusP;        // OPTIONAL
    private BigInteger firstCoefA;            // OPTIONAL
    private BigInteger secondCoefB;        // OPTIONAL
    private byte[]     basePointG;            // OPTIONAL
    private BigInteger orderOfBasePointR;    // OPTIONAL
    private byte[]     publicPointY;        //REQUIRED
    private BigInteger cofactorF;            // OPTIONAL
    private int options;
    private static final int P = 0x01;
    private static final int A = 0x02;
    private static final int B = 0x04;
    private static final int G = 0x08;
    private static final int R = 0x10;
    private static final int Y = 0x20;
    private static final int F = 0x40;

    ECDSAPublicKey(ASN1Sequence seq)
        throws IllegalArgumentException
    {
        Enumeration en = seq.getObjects();

        this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());

        options = 0;
        while (en.hasMoreElements())
        {
            Object obj = en.nextElement();
            
            if (obj instanceof ASN1TaggedObject)
            {
                ASN1TaggedObject to = (ASN1TaggedObject)obj;
                switch (to.getTagNo())
                {
                case 0x1:
                    setPrimeModulusP(UnsignedInteger.getInstance(to).getValue());
                    break;
                case 0x2:
                    setFirstCoefA(UnsignedInteger.getInstance(to).getValue());
                    break;
                case 0x3:
                    setSecondCoefB(UnsignedInteger.getInstance(to).getValue());
                    break;
                case 0x4:
                    setBasePointG(ASN1OctetString.getInstance(to, false));
                    break;
                case 0x5:
                    setOrderOfBasePointR(UnsignedInteger.getInstance(to).getValue());
                    break;
                case 0x6:
                    setPublicPointY(ASN1OctetString.getInstance(to, false));
                    break;
                case 0x7:
                    setCofactorF(UnsignedInteger.getInstance(to).getValue());
                    break;
                default:
                    options = 0;
                    throw new IllegalArgumentException("Unknown Object Identifier!");
                }
            }
            else
            {
                throw new IllegalArgumentException("Unknown Object Identifier!");
            }
        }
        if (options != 0x20 && options != 0x7F)
        {
            throw new IllegalArgumentException("All options must be either present or absent!");
        }
    }

    public ECDSAPublicKey(ASN1ObjectIdentifier usage, byte[] ppY)
        throws IllegalArgumentException
    {
        this.usage = usage;
        setPublicPointY(new DEROctetString(ppY));
    }

    public ECDSAPublicKey(ASN1ObjectIdentifier usage, BigInteger p, BigInteger a, BigInteger b, byte[] basePoint, BigInteger order, byte[] publicPoint, int cofactor)
    {
        this.usage = usage;
        setPrimeModulusP(p);
        setFirstCoefA(a);
        setSecondCoefB(b);
        setBasePointG(new DEROctetString(basePoint));
        setOrderOfBasePointR(order);
        setPublicPointY(new DEROctetString(publicPoint));
        setCofactorF(BigInteger.valueOf(cofactor));
    }

    public ASN1ObjectIdentifier getUsage()
    {
        return usage;
    }

    public byte[] getBasePointG()
    {
        if ((options & G) != 0)
        {
            return Arrays.clone(basePointG);
        }
        else
        {
            return null;
        }
    }

    private void setBasePointG(ASN1OctetString basePointG)
        throws IllegalArgumentException
    {
        if ((options & G) == 0)
        {
            options |= G;
            this.basePointG = basePointG.getOctets();
        }
        else
        {
            throw new IllegalArgumentException("Base Point G already set");
        }
    }

    public BigInteger getCofactorF()
    {
        if ((options & F) != 0)
        {
            return cofactorF;
        }
        else
        {
            return null;
        }
    }

    private void setCofactorF(BigInteger cofactorF)
        throws IllegalArgumentException
    {
        if ((options & F) == 0)
        {
            options |= F;
            this.cofactorF = cofactorF;
        }
        else
        {
            throw new IllegalArgumentException("Cofactor F already set");
        }
    }

    public BigInteger getFirstCoefA()
    {
        if ((options & A) != 0)
        {
            return firstCoefA;
        }
        else
        {
            return null;
        }
    }

    private void setFirstCoefA(BigInteger firstCoefA)
        throws IllegalArgumentException
    {
        if ((options & A) == 0)
        {
            options |= A;
            this.firstCoefA = firstCoefA;
        }
        else
        {
            throw new IllegalArgumentException("First Coef A already set");
        }
    }

    public BigInteger getOrderOfBasePointR()
    {
        if ((options & R) != 0)
        {
            return orderOfBasePointR;
        }
        else
        {
            return null;
        }
    }

    private void setOrderOfBasePointR(BigInteger orderOfBasePointR)
        throws IllegalArgumentException
    {
        if ((options & R) == 0)
        {
            options |= R;
            this.orderOfBasePointR = orderOfBasePointR;
        }
        else
        {
            throw new IllegalArgumentException("Order of base point R already set");
        }
    }

    public BigInteger getPrimeModulusP()
    {
        if ((options & P) != 0)
        {
            return primeModulusP;
        }
        else
        {
            return null;
        }
    }

    private void setPrimeModulusP(BigInteger primeModulusP)
    {
        if ((options & P) == 0)
        {
            options |= P;
            this.primeModulusP = primeModulusP;
        }
        else
        {
            throw new IllegalArgumentException("Prime Modulus P already set");
        }
    }

    public byte[] getPublicPointY()
    {
        if ((options & Y) != 0)
        {
            return Arrays.clone(publicPointY);
        }
        else
        {
            return null;
        }
    }

    private void setPublicPointY(ASN1OctetString publicPointY)
        throws IllegalArgumentException
    {
        if ((options & Y) == 0)
        {
            options |= Y;
            this.publicPointY = publicPointY.getOctets();
        }
        else
        {
            throw new IllegalArgumentException("Public Point Y already set");
        }
    }

    public BigInteger getSecondCoefB()
    {
        if ((options & B) != 0)
        {
            return secondCoefB;
        }
        else
        {
            return null;
        }
    }

    private void setSecondCoefB(BigInteger secondCoefB)
        throws IllegalArgumentException
    {
        if ((options & B) == 0)
        {
            options |= B;
            this.secondCoefB = secondCoefB;
        }
        else
        {
            throw new IllegalArgumentException("Second Coef B already set");
        }
    }

    public boolean hasParameters()
    {
        return primeModulusP != null;
    }

    public ASN1EncodableVector getASN1EncodableVector(ASN1ObjectIdentifier oid, boolean publicPointOnly)
    {
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(oid);

        if (!publicPointOnly)
        {
            v.add(new UnsignedInteger(0x01, getPrimeModulusP()));
            v.add(new UnsignedInteger(0x02, getFirstCoefA()));
            v.add(new UnsignedInteger(0x03, getSecondCoefB()));
            v.add(new DERTaggedObject(false, 0x04, new DEROctetString(getBasePointG())));
            v.add(new UnsignedInteger(0x05, getOrderOfBasePointR()));
        }
        v.add(new DERTaggedObject(false, 0x06, new DEROctetString(getPublicPointY())));
        if (!publicPointOnly)
        {
            v.add(new UnsignedInteger(0x07, getCofactorF()));
        }

        return v;
    }

    public ASN1Primitive toASN1Primitive()
    {
        return new DERSequence(getASN1EncodableVector(usage, !hasParameters()));
    }
}
