/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.onosproject.xran.codecs.ber;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

public class BerTag implements Serializable {

    public static final int UNIVERSAL_CLASS = 0x00;
    public static final int APPLICATION_CLASS = 0x40;
    public static final int CONTEXT_CLASS = 0x80;
    public static final int PRIVATE_CLASS = 0xc0;
    public static final int PRIMITIVE = 0x00;
    public static final int CONSTRUCTED = 0x20;
    public static final int BOOLEAN_TAG = 1;
    public static final int INTEGER_TAG = 2;
    public static final int BIT_STRING_TAG = 3;
    public static final int OCTET_STRING_TAG = 4;
    public static final int NULL_TAG = 5;
    public static final int OBJECT_IDENTIFIER_TAG = 6;
    public static final int OBJECT_DESCRIPTOR_TAG = 7;
    public static final int REAL_TAG = 9;
    public static final int ENUMERATED_TAG = 10;
    public static final int EMBEDDED_PDV_TAG = 11;
    public static final int UTF8_STRING_TAG = 12;
    public static final int TIME_TAG = 14;
    public static final int NUMERIC_STRING_TAG = 18;
    public static final int PRINTABLE_STRING_TAG = 19;
    public static final int TELETEX_STRING_TAG = 20;
    public static final int VIDEOTEX_STRING_TAG = 21;
    public static final int IA5_STRING_TAG = 22;
    public static final int UTC_TIME_TAG = 23;
    public static final int GENERALIZED_TIME_TAG = 24;
    public static final int GRAPHIC_STRING_TAG = 25;
    public static final int VISIBLE_STRING_TAG = 26;
    public static final int GENERAL_STRING_TAG = 27;
    public static final int UNIVERSAL_STRING_TAG = 28;
    public static final int BMP_STRING_TAG = 30;
    public static final int DATE_TAG = 31;
    public static final int TIME_OF_DAY_TAG = 32;
    public static final int DATE_TIME_TAG = 33;
    public static final int DURATION_TAG = 34;
    private static final long serialVersionUID = 1L;
    public byte[] tagBytes = null;
    public int tagClass;
    public int primitive;
    public int tagNumber;

    public BerTag(int identifierClass, int primitive, int tagNumber) {
        this.tagClass = identifierClass;
        this.primitive = primitive;
        this.tagNumber = tagNumber;
        code();
    }

    public BerTag() {
    }

    private void code() {
        if (tagNumber < 31) {
            tagBytes = new byte[1];
            tagBytes[0] = (byte) (tagClass | primitive | tagNumber);
        } else {
            int tagLength = 1;
            while (tagNumber > (Math.pow(2, (7 * tagLength)) - 1)) {
                tagLength++;
            }

            tagBytes = new byte[1 + tagLength];
            tagBytes[0] = (byte) (tagClass | primitive | 31);

            for (int j = 1; j <= (tagLength - 1); j++) {
                tagBytes[j] = (byte) (((tagNumber >> (7 * (tagLength - j))) & 0xff) | 0x80);
            }

            tagBytes[tagLength] = (byte) (tagNumber & 0x7f);

        }
    }

    public int encode(BerByteArrayOutputStream os) throws IOException {
        if (tagBytes == null) {
            code();
        }
        for (int i = (tagBytes.length - 1); i >= 0; i--) {
            os.write(tagBytes[i]);
        }
        return tagBytes.length;
    }

    public int decode(InputStream is) throws IOException {
        int nextByte = is.read();
        if (nextByte == -1) {
            throw new EOFException("Unexpected end of input stream.");
        }

        tagClass = nextByte & 0xC0;
        primitive = nextByte & 0x20;
        tagNumber = nextByte & 0x1f;

        int codeLength = 1;

        if (tagNumber == 0x1f) {
            tagNumber = 0;

            int counter = 0;

            do {
                nextByte = is.read();
                if (nextByte == -1) {
                    throw new EOFException("Unexpected end of input stream.");
                }

                codeLength++;
                if (counter >= 6) {
                    throw new IOException("Invalid Tag");
                }
                tagNumber = tagNumber << 7;
                tagNumber |= (nextByte & 0x7f);
                counter++;
            } while ((nextByte & 0x80) == 0x80);

        }

        return codeLength;
    }

    /**
     * Decodes the Identifier from the ByteArrayInputStream and throws an Exception if it is not equal to itself.
     * Returns the number of bytes read from the InputStream.
     *
     * @param is the input stream to read the identifier from.
     * @return the length of the identifier read.
     * @throws IOException if an exception occurs reading the identifier from the stream.
     */
    public int decodeAndCheck(InputStream is) throws IOException {

        for (Byte identifierByte : tagBytes) {
            int nextByte = is.read();
            if (nextByte == -1) {
                throw new EOFException("Unexpected end of input stream.");
            }

            if (nextByte != (identifierByte & 0xff)) {
                throw new IOException("Identifier does not match!");
            }
        }
        return tagBytes.length;
    }

    public boolean equals(int identifierClass, int primitive, int tagNumber) {
        return (this.tagNumber == tagNumber && this.tagClass == identifierClass && this.primitive == primitive);
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof BerTag)) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        BerTag berIdentifier = (BerTag) obj;
        return (tagNumber == berIdentifier.tagNumber && tagClass == berIdentifier.tagClass
                && primitive == berIdentifier.primitive);
    }

    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash * 31 + tagNumber;
        hash = hash * 31 + tagClass;
        hash = hash * 31 + primitive;
        return hash;
    }

    @Override
    public String toString() {
        return "identifier class: " + tagClass + ", primitive: " + primitive + ", tag number: " + tagNumber;
    }

}
