// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.asn1;

import org.bouncycastle.util.Arrays;
import java.io.IOException;

public abstract class ASN1TaggedObject extends ASN1Primitive implements ASN1TaggedObjectParser
{
    private static final int DECLARED_EXPLICIT = 1;
    private static final int DECLARED_IMPLICIT = 2;
    private static final int PARSED_EXPLICIT = 3;
    private static final int PARSED_IMPLICIT = 4;
    final int explicitness;
    final int tagClass;
    final int tagNo;
    final ASN1Encodable obj;
    
    public static ASN1TaggedObject getInstance(final Object o) {
        if (o == null || o instanceof ASN1TaggedObject) {
            return (ASN1TaggedObject)o;
        }
        if (o instanceof ASN1Encodable) {
            final ASN1Primitive asn1Primitive = ((ASN1Encodable)o).toASN1Primitive();
            if (asn1Primitive instanceof ASN1TaggedObject) {
                return (ASN1TaggedObject)asn1Primitive;
            }
        }
        else if (o instanceof byte[]) {
            try {
                return checkedCast(ASN1Primitive.fromByteArray((byte[])o));
            }
            catch (final IOException ex) {
                throw new IllegalArgumentException("failed to construct tagged object from byte[]: " + ex.getMessage());
            }
        }
        throw new IllegalArgumentException("unknown object in getInstance: " + o.getClass().getName());
    }
    
    public static ASN1TaggedObject getInstance(final Object o, final int n) {
        return ASN1Util.checkTagClass(checkInstance(o), n);
    }
    
    public static ASN1TaggedObject getInstance(final Object o, final int n, final int n2) {
        return ASN1Util.checkTag(checkInstance(o), n, n2);
    }
    
    public static ASN1TaggedObject getInstance(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        return ASN1Util.getExplicitContextBaseTagged(checkInstance(asn1TaggedObject, b));
    }
    
    public static ASN1TaggedObject getInstance(final ASN1TaggedObject asn1TaggedObject, final int n, final boolean b) {
        return ASN1Util.getExplicitBaseTagged(checkInstance(asn1TaggedObject, b), n);
    }
    
    public static ASN1TaggedObject getInstance(final ASN1TaggedObject asn1TaggedObject, final int n, final int n2, final boolean b) {
        return ASN1Util.getExplicitBaseTagged(checkInstance(asn1TaggedObject, b), n, n2);
    }
    
    public static ASN1TaggedObject getOptional(final ASN1Encodable asn1Encodable) {
        if (asn1Encodable == null) {
            throw new NullPointerException("'element' cannot be null");
        }
        if (asn1Encodable instanceof ASN1TaggedObject) {
            return (ASN1TaggedObject)asn1Encodable;
        }
        return null;
    }
    
    public static ASN1TaggedObject getOptional(final ASN1Encodable asn1Encodable, final int n) {
        final ASN1TaggedObject optional = getOptional(asn1Encodable);
        if (optional != null && optional.hasTagClass(n)) {
            return optional;
        }
        return null;
    }
    
    public static ASN1TaggedObject getOptional(final ASN1Encodable asn1Encodable, final int n, final int n2) {
        final ASN1TaggedObject optional = getOptional(asn1Encodable);
        if (optional != null && optional.hasTag(n, n2)) {
            return optional;
        }
        return null;
    }
    
    private static ASN1TaggedObject checkInstance(final Object o) {
        if (o == null) {
            throw new NullPointerException("'obj' cannot be null");
        }
        return getInstance(o);
    }
    
    private static ASN1TaggedObject checkInstance(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        if (!b) {
            throw new IllegalArgumentException("this method not valid for implicitly tagged tagged objects");
        }
        if (asn1TaggedObject == null) {
            throw new NullPointerException("'taggedObject' cannot be null");
        }
        return asn1TaggedObject;
    }
    
    protected ASN1TaggedObject(final boolean b, final int n, final ASN1Encodable asn1Encodable) {
        this(b, 128, n, asn1Encodable);
    }
    
    protected ASN1TaggedObject(final boolean b, final int n, final int n2, final ASN1Encodable asn1Encodable) {
        this(b ? 1 : 2, n, n2, asn1Encodable);
    }
    
    ASN1TaggedObject(final int n, final int n2, final int tagNo, final ASN1Encodable obj) {
        if (null == obj) {
            throw new NullPointerException("'obj' cannot be null");
        }
        if (n2 == 0 || (n2 & 0xC0) != n2) {
            throw new IllegalArgumentException("invalid tag class: " + n2);
        }
        this.explicitness = ((obj instanceof ASN1Choice) ? 1 : n);
        this.tagClass = n2;
        this.tagNo = tagNo;
        this.obj = obj;
    }
    
    @Override
    final boolean asn1Equals(final ASN1Primitive asn1Primitive) {
        if (!(asn1Primitive instanceof ASN1TaggedObject)) {
            return false;
        }
        final ASN1TaggedObject asn1TaggedObject = (ASN1TaggedObject)asn1Primitive;
        if (this.tagNo != asn1TaggedObject.tagNo || this.tagClass != asn1TaggedObject.tagClass) {
            return false;
        }
        if (this.explicitness != asn1TaggedObject.explicitness && this.isExplicit() != asn1TaggedObject.isExplicit()) {
            return false;
        }
        final ASN1Primitive asn1Primitive2 = this.obj.toASN1Primitive();
        final ASN1Primitive asn1Primitive3 = asn1TaggedObject.obj.toASN1Primitive();
        if (asn1Primitive2 == asn1Primitive3) {
            return true;
        }
        if (!this.isExplicit()) {
            try {
                return Arrays.areEqual(this.getEncoded(), asn1TaggedObject.getEncoded());
            }
            catch (final IOException ex) {
                return false;
            }
        }
        return asn1Primitive2.asn1Equals(asn1Primitive3);
    }
    
    @Override
    public int hashCode() {
        return this.tagClass * 7919 ^ this.tagNo ^ (this.isExplicit() ? 15 : 240) ^ this.obj.toASN1Primitive().hashCode();
    }
    
    @Override
    public int getTagClass() {
        return this.tagClass;
    }
    
    @Override
    public int getTagNo() {
        return this.tagNo;
    }
    
    @Override
    public boolean hasContextTag() {
        return this.tagClass == 128;
    }
    
    @Override
    public boolean hasContextTag(final int n) {
        return this.tagClass == 128 && this.tagNo == n;
    }
    
    @Override
    public boolean hasTag(final int n, final int n2) {
        return this.tagClass == n && this.tagNo == n2;
    }
    
    @Override
    public boolean hasTagClass(final int n) {
        return this.tagClass == n;
    }
    
    public boolean isExplicit() {
        switch (this.explicitness) {
            case 1:
            case 3: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    
    boolean isParsed() {
        switch (this.explicitness) {
            case 3:
            case 4: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    
    public ASN1Object getBaseObject() {
        return (this.obj instanceof ASN1Object) ? ((ASN1Object)this.obj) : this.obj.toASN1Primitive();
    }
    
    public ASN1Object getExplicitBaseObject() {
        if (!this.isExplicit()) {
            throw new IllegalStateException("object implicit - explicit expected.");
        }
        return (this.obj instanceof ASN1Object) ? ((ASN1Object)this.obj) : this.obj.toASN1Primitive();
    }
    
    public ASN1TaggedObject getExplicitBaseTagged() {
        if (!this.isExplicit()) {
            throw new IllegalStateException("object implicit - explicit expected.");
        }
        return checkedCast(this.obj.toASN1Primitive());
    }
    
    public ASN1TaggedObject getImplicitBaseTagged(final int i, final int n) {
        if (i == 0 || (i & 0xC0) != i) {
            throw new IllegalArgumentException("invalid base tag class: " + i);
        }
        switch (this.explicitness) {
            case 1: {
                throw new IllegalStateException("object explicit - implicit expected.");
            }
            case 2: {
                return ASN1Util.checkTag(checkedCast(this.obj.toASN1Primitive()), i, n);
            }
            default: {
                return this.replaceTag(i, n);
            }
        }
    }
    
    public ASN1Primitive getBaseUniversal(final boolean b, final int i) {
        final ASN1UniversalType value = ASN1UniversalTypes.get(i);
        if (null == value) {
            throw new IllegalArgumentException("unsupported UNIVERSAL tag number: " + i);
        }
        return this.getBaseUniversal(b, value);
    }
    
    ASN1Primitive getBaseUniversal(final boolean b, final ASN1UniversalType asn1UniversalType) {
        if (b) {
            if (!this.isExplicit()) {
                throw new IllegalStateException("object implicit - explicit expected.");
            }
            return asn1UniversalType.checkedCast(this.obj.toASN1Primitive());
        }
        else {
            if (1 == this.explicitness) {
                throw new IllegalStateException("object explicit - implicit expected.");
            }
            final ASN1Primitive asn1Primitive = this.obj.toASN1Primitive();
            switch (this.explicitness) {
                case 3: {
                    return asn1UniversalType.fromImplicitConstructed(this.rebuildConstructed(asn1Primitive));
                }
                case 4: {
                    if (asn1Primitive instanceof ASN1Sequence) {
                        return asn1UniversalType.fromImplicitConstructed((ASN1Sequence)asn1Primitive);
                    }
                    return asn1UniversalType.fromImplicitPrimitive((DEROctetString)asn1Primitive);
                }
                default: {
                    return asn1UniversalType.checkedCast(asn1Primitive);
                }
            }
        }
    }
    
    @Override
    public ASN1Encodable parseBaseUniversal(final boolean b, final int n) throws IOException {
        final ASN1Primitive baseUniversal = this.getBaseUniversal(b, n);
        switch (n) {
            case 3: {
                return ((ASN1BitString)baseUniversal).parser();
            }
            case 4: {
                return ((ASN1OctetString)baseUniversal).parser();
            }
            case 16: {
                return ((ASN1Sequence)baseUniversal).parser();
            }
            case 17: {
                return ((ASN1Set)baseUniversal).parser();
            }
            default: {
                return baseUniversal;
            }
        }
    }
    
    @Override
    public ASN1Encodable parseExplicitBaseObject() throws IOException {
        return this.getExplicitBaseObject();
    }
    
    @Override
    public ASN1TaggedObjectParser parseExplicitBaseTagged() throws IOException {
        return this.getExplicitBaseTagged();
    }
    
    @Override
    public ASN1TaggedObjectParser parseImplicitBaseTagged(final int n, final int n2) throws IOException {
        return this.getImplicitBaseTagged(n, n2);
    }
    
    @Override
    public final ASN1Primitive getLoadedObject() {
        return this;
    }
    
    abstract ASN1Sequence rebuildConstructed(final ASN1Primitive p0);
    
    abstract ASN1TaggedObject replaceTag(final int p0, final int p1);
    
    @Override
    ASN1Primitive toDERObject() {
        return new DERTaggedObject(this.explicitness, this.tagClass, this.tagNo, this.obj);
    }
    
    @Override
    ASN1Primitive toDLObject() {
        return new DLTaggedObject(this.explicitness, this.tagClass, this.tagNo, this.obj);
    }
    
    @Override
    public String toString() {
        return ASN1Util.getTagText(this.tagClass, this.tagNo) + this.obj;
    }
    
    static ASN1Primitive createConstructedDL(final int n, final int n2, final ASN1EncodableVector asn1EncodableVector) {
        return (asn1EncodableVector.size() == 1) ? new DLTaggedObject(3, n, n2, asn1EncodableVector.get(0)) : new DLTaggedObject(4, n, n2, DLFactory.createSequence(asn1EncodableVector));
    }
    
    static ASN1Primitive createConstructedIL(final int n, final int n2, final ASN1EncodableVector asn1EncodableVector) {
        return (asn1EncodableVector.size() == 1) ? new BERTaggedObject(3, n, n2, asn1EncodableVector.get(0)) : new BERTaggedObject(4, n, n2, BERFactory.createSequence(asn1EncodableVector));
    }
    
    static ASN1Primitive createPrimitive(final int n, final int n2, final byte[] array) {
        return new DLTaggedObject(4, n, n2, new DEROctetString(array));
    }
    
    private static ASN1TaggedObject checkedCast(final ASN1Primitive asn1Primitive) {
        if (asn1Primitive instanceof ASN1TaggedObject) {
            return (ASN1TaggedObject)asn1Primitive;
        }
        throw new IllegalStateException("unexpected object: " + asn1Primitive.getClass().getName());
    }
}
