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

package org.bouncycastle.asn1;

import java.util.concurrent.ConcurrentHashMap;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
import java.io.IOException;
import java.util.concurrent.ConcurrentMap;

public class ASN1ObjectIdentifier extends ASN1Primitive
{
    static final ASN1UniversalType TYPE;
    private static final int MAX_CONTENTS_LENGTH = 4096;
    private static final int MAX_IDENTIFIER_LENGTH = 16385;
    private static final long LONG_LIMIT = 72057594037927808L;
    private static final ConcurrentMap<OidHandle, ASN1ObjectIdentifier> pool;
    private final byte[] contents;
    private String identifier;
    
    public static ASN1ObjectIdentifier fromContents(final byte[] array) {
        if (array == null) {
            throw new NullPointerException("'contents' cannot be null");
        }
        return createPrimitive(array, true);
    }
    
    public static ASN1ObjectIdentifier getInstance(final Object o) {
        if (o == null || o instanceof ASN1ObjectIdentifier) {
            return (ASN1ObjectIdentifier)o;
        }
        if (o instanceof ASN1Encodable) {
            final ASN1Primitive asn1Primitive = ((ASN1Encodable)o).toASN1Primitive();
            if (asn1Primitive instanceof ASN1ObjectIdentifier) {
                return (ASN1ObjectIdentifier)asn1Primitive;
            }
        }
        else if (o instanceof byte[]) {
            try {
                return (ASN1ObjectIdentifier)ASN1ObjectIdentifier.TYPE.fromByteArray((byte[])o);
            }
            catch (final IOException ex) {
                throw new IllegalArgumentException("failed to construct object identifier from byte[]: " + ex.getMessage());
            }
        }
        throw new IllegalArgumentException("illegal object in getInstance: " + o.getClass().getName());
    }
    
    public static ASN1ObjectIdentifier getInstance(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        if (!b && !asn1TaggedObject.isParsed() && asn1TaggedObject.hasContextTag()) {
            final ASN1Primitive asn1Primitive = asn1TaggedObject.getBaseObject().toASN1Primitive();
            if (!(asn1Primitive instanceof ASN1ObjectIdentifier)) {
                return fromContents(ASN1OctetString.getInstance(asn1Primitive).getOctets());
            }
        }
        return (ASN1ObjectIdentifier)ASN1ObjectIdentifier.TYPE.getContextTagged(asn1TaggedObject, b);
    }
    
    public static ASN1ObjectIdentifier getTagged(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        return (ASN1ObjectIdentifier)ASN1ObjectIdentifier.TYPE.getTagged(asn1TaggedObject, b);
    }
    
    public static ASN1ObjectIdentifier tryFromID(final String s) {
        if (s == null) {
            throw new NullPointerException("'identifier' cannot be null");
        }
        if (s.length() <= 16385 && isValidIdentifier(s)) {
            final byte[] identifier = parseIdentifier(s);
            if (identifier.length <= 4096) {
                return new ASN1ObjectIdentifier(identifier, s);
            }
        }
        return null;
    }
    
    public ASN1ObjectIdentifier(final String identifier) {
        checkIdentifier(identifier);
        final byte[] identifier2 = parseIdentifier(identifier);
        checkContentsLength(identifier2.length);
        this.contents = identifier2;
        this.identifier = identifier;
    }
    
    private ASN1ObjectIdentifier(final byte[] contents, final String identifier) {
        this.contents = contents;
        this.identifier = identifier;
    }
    
    public ASN1ObjectIdentifier branch(final String str) {
        ASN1RelativeOID.checkIdentifier(str);
        byte[] array;
        if (str.length() <= 2) {
            checkContentsLength(this.contents.length + 1);
            int n = str.charAt(0) - '0';
            if (str.length() == 2) {
                n = n * 10 + (str.charAt(1) - '0');
            }
            array = Arrays.append(this.contents, (byte)n);
        }
        else {
            final byte[] identifier = ASN1RelativeOID.parseIdentifier(str);
            checkContentsLength(this.contents.length + identifier.length);
            array = Arrays.concatenate(this.contents, identifier);
        }
        return new ASN1ObjectIdentifier(array, this.getId() + "." + str);
    }
    
    public synchronized String getId() {
        if (this.identifier == null) {
            this.identifier = parseContents(this.contents);
        }
        return this.identifier;
    }
    
    public boolean on(final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        final byte[] contents = this.contents;
        final byte[] contents2 = asn1ObjectIdentifier.contents;
        final int length = contents2.length;
        return contents.length > length && Arrays.areEqual(contents, 0, length, contents2, 0, length);
    }
    
    @Override
    boolean encodeConstructed() {
        return false;
    }
    
    @Override
    int encodedLength(final boolean b) {
        return ASN1OutputStream.getLengthOfEncodingDL(b, this.contents.length);
    }
    
    @Override
    void encode(final ASN1OutputStream asn1OutputStream, final boolean b) throws IOException {
        asn1OutputStream.writeEncodingDL(b, 6, this.contents);
    }
    
    @Override
    public int hashCode() {
        return Arrays.hashCode(this.contents);
    }
    
    @Override
    boolean asn1Equals(final ASN1Primitive asn1Primitive) {
        return this == asn1Primitive || (asn1Primitive instanceof ASN1ObjectIdentifier && Arrays.areEqual(this.contents, ((ASN1ObjectIdentifier)asn1Primitive).contents));
    }
    
    @Override
    public String toString() {
        return this.getId();
    }
    
    static void checkContentsLength(final int n) {
        if (n > 4096) {
            throw new IllegalArgumentException("exceeded OID contents length limit");
        }
    }
    
    static void checkIdentifier(final String str) {
        if (str == null) {
            throw new NullPointerException("'identifier' cannot be null");
        }
        if (str.length() > 16385) {
            throw new IllegalArgumentException("exceeded OID contents length limit");
        }
        if (!isValidIdentifier(str)) {
            throw new IllegalArgumentException("string " + str + " not a valid OID");
        }
    }
    
    static ASN1ObjectIdentifier createPrimitive(final byte[] array, final boolean b) {
        checkContentsLength(array.length);
        final ASN1ObjectIdentifier asn1ObjectIdentifier = ASN1ObjectIdentifier.pool.get(new OidHandle(array));
        if (asn1ObjectIdentifier != null) {
            return asn1ObjectIdentifier;
        }
        if (!ASN1RelativeOID.isValidContents(array)) {
            throw new IllegalArgumentException("invalid OID contents");
        }
        return new ASN1ObjectIdentifier(b ? Arrays.clone(array) : array, null);
    }
    
    private static boolean isValidIdentifier(final String s) {
        if (s.length() < 3 || s.charAt(1) != '.') {
            return false;
        }
        final char char1 = s.charAt(0);
        return char1 >= '0' && char1 <= '2' && ASN1RelativeOID.isValidIdentifier(s, 2) && (char1 == '2' || (s.length() == 3 || s.charAt(3) == '.') || ((s.length() == 4 || s.charAt(4) == '.') && s.charAt(2) < '4'));
    }
    
    private static String parseContents(final byte[] array) {
        final StringBuilder sb = new StringBuilder();
        long val = 0L;
        BigInteger bigInteger = null;
        int n = 1;
        for (int i = 0; i != array.length; ++i) {
            final int n2 = array[i] & 0xFF;
            if (val <= 72057594037927808L) {
                long lng = val + (n2 & 0x7F);
                if ((n2 & 0x80) == 0x0) {
                    if (n != 0) {
                        if (lng < 40L) {
                            sb.append('0');
                        }
                        else if (lng < 80L) {
                            sb.append('1');
                            lng -= 40L;
                        }
                        else {
                            sb.append('2');
                            lng -= 80L;
                        }
                        n = 0;
                    }
                    sb.append('.');
                    sb.append(lng);
                    val = 0L;
                }
                else {
                    val = lng << 7;
                }
            }
            else {
                if (bigInteger == null) {
                    bigInteger = BigInteger.valueOf(val);
                }
                BigInteger obj = bigInteger.or(BigInteger.valueOf(n2 & 0x7F));
                if ((n2 & 0x80) == 0x0) {
                    if (n != 0) {
                        sb.append('2');
                        obj = obj.subtract(BigInteger.valueOf(80L));
                        n = 0;
                    }
                    sb.append('.');
                    sb.append(obj);
                    bigInteger = null;
                    val = 0L;
                }
                else {
                    bigInteger = obj.shiftLeft(7);
                }
            }
        }
        return sb.toString();
    }
    
    private static byte[] parseIdentifier(final String s) {
        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        final OIDTokenizer oidTokenizer = new OIDTokenizer(s);
        final int n = Integer.parseInt(oidTokenizer.nextToken()) * 40;
        final String nextToken = oidTokenizer.nextToken();
        if (nextToken.length() <= 18) {
            ASN1RelativeOID.writeField(byteArrayOutputStream, n + Long.parseLong(nextToken));
        }
        else {
            ASN1RelativeOID.writeField(byteArrayOutputStream, new BigInteger(nextToken).add(BigInteger.valueOf(n)));
        }
        while (oidTokenizer.hasMoreTokens()) {
            final String nextToken2 = oidTokenizer.nextToken();
            if (nextToken2.length() <= 18) {
                ASN1RelativeOID.writeField(byteArrayOutputStream, Long.parseLong(nextToken2));
            }
            else {
                ASN1RelativeOID.writeField(byteArrayOutputStream, new BigInteger(nextToken2));
            }
        }
        return byteArrayOutputStream.toByteArray();
    }
    
    public ASN1ObjectIdentifier intern() {
        final OidHandle oidHandle = new OidHandle(this.contents);
        final ASN1ObjectIdentifier asn1ObjectIdentifier = ASN1ObjectIdentifier.pool.get(oidHandle);
        if (asn1ObjectIdentifier == null) {
            synchronized (ASN1ObjectIdentifier.pool) {
                if (!ASN1ObjectIdentifier.pool.containsKey(oidHandle)) {
                    ASN1ObjectIdentifier.pool.put(oidHandle, this);
                    return this;
                }
                return (ASN1ObjectIdentifier)ASN1ObjectIdentifier.pool.get(oidHandle);
            }
        }
        return asn1ObjectIdentifier;
    }
    
    static {
        TYPE = new ASN1UniversalType(6) {
            @Override
            ASN1Primitive fromImplicitPrimitive(final DEROctetString derOctetString) {
                return ASN1ObjectIdentifier.createPrimitive(derOctetString.getOctets(), false);
            }
        };
        pool = new ConcurrentHashMap<OidHandle, ASN1ObjectIdentifier>();
    }
    
    static class OidHandle
    {
        private final int key;
        private final byte[] contents;
        
        OidHandle(final byte[] contents) {
            this.key = Arrays.hashCode(contents);
            this.contents = contents;
        }
        
        @Override
        public int hashCode() {
            return this.key;
        }
        
        @Override
        public boolean equals(final Object o) {
            return o instanceof OidHandle && Arrays.areEqual(this.contents, ((OidHandle)o).contents);
        }
    }
}
