/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
* @author Alexander V. Esin, Stepan M. Mishura
* @version $Revision$
*/

package org.apache.harmony.security.x501;

import java.io.IOException;
import java.nio.charset.Charsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import javax.security.auth.x500.X500Principal;
import org.apache.harmony.security.Util;
import org.apache.harmony.security.asn1.ASN1Constants;
import org.apache.harmony.security.asn1.ASN1Oid;
import org.apache.harmony.security.asn1.ASN1Sequence;
import org.apache.harmony.security.asn1.ASN1StringType;
import org.apache.harmony.security.asn1.ASN1Type;
import org.apache.harmony.security.asn1.BerInputStream;
import org.apache.harmony.security.asn1.BerOutputStream;
import org.apache.harmony.security.utils.ObjectIdentifier;


/**
 * X.501 AttributeTypeAndValue
 */
public class AttributeTypeAndValue {

    // Country code attribute (name from RFC 1779)
    private static final ObjectIdentifier C;

    // Common name attribute (name from RFC 1779)
    private static final ObjectIdentifier CN;

    // Domain component attribute (name from RFC 2253)
    private static final ObjectIdentifier DC;

    // DN qualifier attribute (name from API spec)
    private static final ObjectIdentifier DNQ;

    private static final ObjectIdentifier DNQUALIFIER;

    // Email Address attribute (name from API spec)
    private static final ObjectIdentifier EMAILADDRESS;

    // Generation attribute (qualifies an individual's name)
    // (name from API spec)
    private static final ObjectIdentifier GENERATION;

    // Given name attribute (name from API spec)
    private static final ObjectIdentifier GIVENNAME;

    // Initials attribute (initials of an individual's name)
    // (name from API spec)
    private static final ObjectIdentifier INITIALS;

    // Name of a locality attribute (name from RFC 1779)
    private static final ObjectIdentifier L;

    // Organization name attribute (name from RFC 1779)
    private static final ObjectIdentifier O;

    // Organizational unit name attribute (name from RFC 1779)
    private static final ObjectIdentifier OU;

    // Serial number attribute (serial number of a device)
    // (name from API spec)
    private static final ObjectIdentifier SERIALNUMBER;

    // Attribute for the full name of a state or province
    // (name from RFC 1779)
    private static final ObjectIdentifier ST;

    // Street attribute (name from RFC 1779)
    private static final ObjectIdentifier STREET;

    // Surname attribute (comes from an individual's parent name)
    // (name from API spec)
    private static final ObjectIdentifier SURNAME;

    // Title attribute (object in an organization)(name from API spec)
    private static final ObjectIdentifier T;

    // User identifier attribute (name from RFC 2253)
    private static final ObjectIdentifier UID;

    //
    // OID's pool
    //

    // pool's capacity
    private static final int CAPACITY;

    // pool's size
    private static final int SIZE;

    // pool: contains all recognizable attribute type keywords
    private static final ObjectIdentifier[][] KNOWN_OIDS;

    // known keywords attribute
    private static final HashMap KNOWN_NAMES = new HashMap(30);

    // known attribute types for RFC1779 (see Table 1)
    private static final HashMap RFC1779_NAMES = new HashMap(10);

    // known attribute types for RFC2253
    // (see 2.3.  Converting AttributeTypeAndValue)
    private static final HashMap RFC2253_NAMES = new HashMap(10);

    // known attribute types for RFC2459 (see API spec.)
    private static final HashMap RFC2459_NAMES = new HashMap(10);

    static {

        // pool initialization
        CAPACITY = 10;
        SIZE = 10;
        KNOWN_OIDS = new ObjectIdentifier[SIZE][CAPACITY];

        // init known attribute type keywords
        C = new ObjectIdentifier(new int[] { 2, 5, 4, 6 }, "C", RFC1779_NAMES);
        CN = new ObjectIdentifier(new int[] { 2, 5, 4, 3 }, "CN", RFC1779_NAMES);

        DC = new ObjectIdentifier(
                new int[] { 0, 9, 2342, 19200300, 100, 1, 25 }, "DC",
                RFC2253_NAMES);
        // DN qualifier aliases
        DNQ = new ObjectIdentifier(new int[] { 2, 5, 4, 46 }, "DNQ",
                RFC2459_NAMES);
        DNQUALIFIER = new ObjectIdentifier(new int[] { 2, 5, 4, 46 },
                "DNQUALIFIER", RFC2459_NAMES);

        EMAILADDRESS = new ObjectIdentifier(new int[] { 1, 2, 840, 113549, 1,
                9, 1 }, "EMAILADDRESS", RFC2459_NAMES);

        GENERATION = new ObjectIdentifier(new int[] { 2, 5, 4, 44 },
                "GENERATION", RFC2459_NAMES);
        GIVENNAME = new ObjectIdentifier(new int[] { 2, 5, 4, 42 },
                "GIVENNAME", RFC2459_NAMES);

        INITIALS = new ObjectIdentifier(new int[] { 2, 5, 4, 43 }, "INITIALS",
                RFC2459_NAMES);

        L = new ObjectIdentifier(new int[] { 2, 5, 4, 7 }, "L", RFC1779_NAMES);

        O = new ObjectIdentifier(new int[] { 2, 5, 4, 10 }, "O", RFC1779_NAMES);
        OU = new ObjectIdentifier(new int[] { 2, 5, 4, 11 }, "OU",
                RFC1779_NAMES);

        SERIALNUMBER = new ObjectIdentifier(new int[] { 2, 5, 4, 5 },
                "SERIALNUMBER", RFC2459_NAMES);
        ST = new ObjectIdentifier(new int[] { 2, 5, 4, 8 }, "ST", RFC1779_NAMES);
        STREET = new ObjectIdentifier(new int[] { 2, 5, 4, 9 }, "STREET",
                RFC1779_NAMES);
        SURNAME = new ObjectIdentifier(new int[] { 2, 5, 4, 4 }, "SURNAME",
                RFC2459_NAMES);

        T = new ObjectIdentifier(new int[] { 2, 5, 4, 12 }, "T", RFC2459_NAMES);

        UID = new ObjectIdentifier(
                new int[] { 0, 9, 2342, 19200300, 100, 1, 1 }, "UID",
                RFC2253_NAMES);

        //
        // RFC1779
        //
        RFC1779_NAMES.put(CN.getName(), CN);
        RFC1779_NAMES.put(L.getName(), L);
        RFC1779_NAMES.put(ST.getName(), ST);
        RFC1779_NAMES.put(O.getName(), O);
        RFC1779_NAMES.put(OU.getName(), OU);
        RFC1779_NAMES.put(C.getName(), C);
        RFC1779_NAMES.put(STREET.getName(), STREET);

        //
        // RFC2253: includes all from RFC1779
        //
        RFC2253_NAMES.putAll(RFC1779_NAMES);

        RFC2253_NAMES.put(DC.getName(), DC);
        RFC2253_NAMES.put(UID.getName(), UID);

        //
        // RFC2459
        //
        RFC2459_NAMES.put(DNQ.getName(), DNQ);
        RFC2459_NAMES.put(DNQUALIFIER.getName(), DNQUALIFIER);
        RFC2459_NAMES.put(EMAILADDRESS.getName(), EMAILADDRESS);
        RFC2459_NAMES.put(GENERATION.getName(), GENERATION);
        RFC2459_NAMES.put(GIVENNAME.getName(), GIVENNAME);
        RFC2459_NAMES.put(INITIALS.getName(), INITIALS);
        RFC2459_NAMES.put(SERIALNUMBER.getName(), SERIALNUMBER);
        RFC2459_NAMES.put(SURNAME.getName(), SURNAME);
        RFC2459_NAMES.put(T.getName(), T);

        //
        // Init KNOWN_OIDS pool
        //

        // add from RFC2253 (includes RFC1779)
        Iterator it = RFC2253_NAMES.values().iterator();
        while (it.hasNext()) {
            addOID((ObjectIdentifier) it.next());
        }

        // add attributes from RFC2459
        it = RFC2459_NAMES.values().iterator();
        while (it.hasNext()) {
            Object o = it.next();

            //don't add DNQUALIFIER because it has the same oid as DNQ
            if (!(o == DNQUALIFIER)) {
                addOID((ObjectIdentifier) o);
            }
        }

        //
        // Init KNOWN_NAMES pool
        //

        KNOWN_NAMES.putAll(RFC2253_NAMES); // RFC2253 includes RFC1779
        KNOWN_NAMES.putAll(RFC2459_NAMES);
    }

    //Attribute type
    private final ObjectIdentifier oid;

    //Attribute value
    private AttributeValue value;

    // for decoder only
    private AttributeTypeAndValue(int[] oid, AttributeValue value)
            throws IOException {

        ObjectIdentifier thisOid = getOID(oid);
        if (thisOid == null) {
            thisOid = new ObjectIdentifier(oid);
        }
        this.oid = thisOid;
        this.value = value;
    }

    /**
     * Creates AttributeTypeAndValue with OID and AttributeValue. Parses OID
     * string representation
     *
     * @param sOid
     *            string representation of OID
     * @param value
     *            attribute value
     * @throws IOException
     *             if OID can not be created from its string representation
     */
    public AttributeTypeAndValue(String sOid, AttributeValue value)
            throws IOException {
        if (sOid.charAt(0) >= '0' && sOid.charAt(0) <= '9') {

            int[] array = org.apache.harmony.security.asn1.ObjectIdentifier
                    .toIntArray(sOid);

            ObjectIdentifier thisOid = getOID(array);
            if (thisOid == null) {
                thisOid = new ObjectIdentifier(array);
            }
            this.oid = thisOid;

        } else {
            this.oid = (ObjectIdentifier) KNOWN_NAMES.get(Util.toUpperCase(sOid));
            if (this.oid == null) {
                throw new IOException("Unrecognizable attribute name: " + sOid);
            }
        }
        this.value = value;
    }

    /**
     * Appends AttributeTypeAndValue string representation
     *
     * @param attrFormat - format of DN
     * @param buf - string buffer to be used
     */
    public void appendName(String attrFormat, StringBuffer buf) {

        boolean hexFormat = false;
        if (X500Principal.RFC1779.equals(attrFormat)) {
            if (RFC1779_NAMES == oid.getGroup()) {
                buf.append(oid.getName());
            } else {
                buf.append(oid.toOIDString());
            }

            buf.append('=');
            if (value.escapedString == value.getHexString()) {
                //FIXME all chars in upper case
                buf.append(Util.toUpperCase(value.getHexString()));
            } else if (value.escapedString.length() != value.rawString.length()) {
                // was escaped
                value.appendQEString(buf);
            } else {
                buf.append(value.escapedString);
            }
        } else {
            Object group = oid.getGroup();
            // RFC2253 includes names from RFC1779
            if (RFC1779_NAMES == group || RFC2253_NAMES == group) {
                buf.append(oid.getName());

                if (X500Principal.CANONICAL.equals(attrFormat)) {
                    // only PrintableString and UTF8String in string format
                    // all others are output in hex format
                    // BEGIN android-changed
                    // no hex for teletex; see bug 2102191
                    int tag = value.getTag();
                    if (!ASN1StringType.UTF8STRING.checkTag(tag)
                            && !ASN1StringType.PRINTABLESTRING.checkTag(tag)
                            && !ASN1StringType.TELETEXSTRING.checkTag(tag)) {
                        hexFormat = true;
                    }
                    // END android-changed
                }

            } else {
                buf.append(oid.toString());
                hexFormat = true;
            }

            buf.append('=');

            if (hexFormat) {
                buf.append(value.getHexString());
            } else {
                if (X500Principal.CANONICAL.equals(attrFormat)) {
                    buf.append(value.makeCanonical());
                } else {
                    buf.append(value.escapedString);
                }
            }
        }
    }

    /**
     * Gets type of the AttributeTypeAndValue
     *
     * @return ObjectIdentifier
     */
    public ObjectIdentifier getType() {
        return oid;
    }

    /**
     * According to RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt)
     * X.501 AttributeTypeAndValue structure is defined as follows:
     *
     *   AttributeTypeAndValue ::= SEQUENCE {
     *      type     AttributeType,
     *      value    AttributeValue }
     *
     *    AttributeType ::= OBJECT IDENTIFIER
     *
     *    AttributeValue ::= ANY DEFINED BY AttributeType
     *    ...
     *    DirectoryString ::= CHOICE {
     *          teletexString           TeletexString (SIZE (1..MAX)),
     *          printableString         PrintableString (SIZE (1..MAX)),
     *          universalString         UniversalString (SIZE (1..MAX)),
     *          utf8String              UTF8String (SIZE (1.. MAX)),
     *          bmpString               BMPString (SIZE (1..MAX)) }
     *
     */

    public static final ASN1Type attributeValue = new ASN1Type(
            ASN1Constants.TAG_PRINTABLESTRING) {

        public boolean checkTag(int tag) {
            return true;
        }

        public Object decode(BerInputStream in) throws IOException {

            // FIXME what about constr???
            String str = null;
            if (DirectoryString.ASN1.checkTag(in.tag)) {
                // has string representation
                str = (String) DirectoryString.ASN1.decode(in);
            } else {
                // gets octets only
                in.readContent();
            }

            byte[] bytesEncoded = new byte[in.getOffset() - in.getTagOffset()];
            System.arraycopy(in.getBuffer(), in.getTagOffset(), bytesEncoded,
                    0, bytesEncoded.length);

            return new AttributeValue(str, bytesEncoded, in.tag);
        }

        public Object getDecodedObject(BerInputStream in) throws IOException {
            // stub to avoid wrong decoder usage
            throw new RuntimeException("AttributeValue getDecodedObject MUST NOT be invoked");
        }

        //
        // Encode
        //
        public void encodeASN(BerOutputStream out) {

            AttributeValue av = (AttributeValue) out.content;

            if (av.encoded != null) {
                out.content = av.encoded;
                out.encodeANY();
            } else {
                out.encodeTag(av.getTag());
                out.content = av.bytes;
                out.encodeString();
            }
        }

        public void setEncodingContent(BerOutputStream out) {

            AttributeValue av = (AttributeValue) out.content;

            if (av.encoded != null) {
                out.length = av.encoded.length;
            } else {

                if (av.getTag() == ASN1Constants.TAG_UTF8STRING) {

                    out.content = av.rawString;

                    ASN1StringType.UTF8STRING.setEncodingContent(out);

                    av.bytes = (byte[]) out.content;
                    out.content = av;
                } else {
                    av.bytes = av.rawString.getBytes(Charsets.UTF_8);
                    out.length = av.bytes.length;
                }
            }
        }

        public void encodeContent(BerOutputStream out) {
            // stub to avoid wrong encoder usage
            throw new RuntimeException("AttributeValue encodeContent MUST NOT be invoked");
        }

        public int getEncodedLength(BerOutputStream out) { //FIXME name

            AttributeValue av = (AttributeValue) out.content;

            if (av.encoded != null) {
                return out.length;
            } else {
                return super.getEncodedLength(out);
            }
        }
    };

    public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
            ASN1Oid.getInstance(), attributeValue }) {

        protected Object getDecodedObject(BerInputStream in) throws IOException {
            Object[] values = (Object[]) in.content;
            return new AttributeTypeAndValue((int[]) values[0],
                    (AttributeValue) values[1]);
        }

        protected void getValues(Object object, Object[] values) {
            AttributeTypeAndValue atav = (AttributeTypeAndValue) object;

            values[0] = atav.oid.getOid();
            values[1] = atav.value;
        }
    };

    // returns known OID or null
    private static ObjectIdentifier getOID(int[] oid) {

        int index = hashIntArray(oid) % CAPACITY;

        // look for OID in the pool
        ObjectIdentifier[] list = KNOWN_OIDS[index];
        for (int i = 0; list[i] != null; i++) {
            if (Arrays.equals(oid, list[i].getOid())) {
                return list[i];
            }
        }
        return null;
    }

    // adds known OID to pool
    // for static AttributeTypeAndValue initialization only
    private static void addOID(ObjectIdentifier oid) {

        int[] newOid = oid.getOid();
        int index = hashIntArray(newOid) % CAPACITY;

        // look for OID in the pool
        ObjectIdentifier[] list = KNOWN_OIDS[index];
        int i = 0;
        for (; list[i] != null; i++) {

            // check wrong static initialization: no duplicate OIDs
            if (Arrays.equals(newOid, list[i].getOid())) {
                throw new Error("ObjectIdentifier: invalid static initialization; " +
                        "duplicate OIDs: " + oid.getName() + " " + list[i].getName());
            }
        }

        // check : to avoid NPE
        if (i == (CAPACITY - 1)) {
            throw new Error("ObjectIdentifier: invalid static initialization; " +
                    "small OID pool capacity");
        }
        list[i] = oid;
    }

    // returns hash for array of integers
    private static int hashIntArray(int[] oid) {
        int intHash = 0;
        for (int i = 0; i < oid.length && i < 4; i++) {
            intHash += oid[i] << (8 * i); //TODO what about to find better one?
        }
        return intHash & 0x7FFFFFFF; // only positive
    }
}
