/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed 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.
 */

package org.onosproject.bgpio.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.primitives.Ints;

/**
 * Provides methods to parse attribute header, validate length and type.
 */
public class Validation {
    private static final Logger log = LoggerFactory.getLogger(Validation.class);
    public static final byte FIRST_BIT = (byte) 0x80;
    public static final byte SECOND_BIT = 0x40;
    public static final byte THIRD_BIT = 0x20;
    public static final byte FOURTH_BIT = (byte) 0x10;
    public static final byte IPV4_SIZE = 4;
    private boolean firstBit;
    private boolean secondBit;
    private boolean thirdBit;
    private boolean fourthBit;
    private int len;
    private boolean isShort;

    /**
     * Constructor to initialize parameter.
     *
     * @param firstBit in AttributeFlags
     * @param secondBit in AttributeFlags
     * @param thirdBit in AttributeFlags
     * @param fourthBit in AttributeFlags
     * @param len length
     * @param isShort true if length is read as short otherwise false
     */
    Validation(boolean firstBit, boolean secondBit, boolean thirdBit, boolean fourthBit, int len, boolean isShort) {
        this.firstBit = firstBit;
        this.secondBit = secondBit;
        this.thirdBit = thirdBit;
        this.fourthBit = fourthBit;
        this.len = len;
        this.isShort = isShort;
    }

    /**
     * Parses attribute Header.
     *
     * @param cb ChannelBuffer
     * @return object of Validation
     */
    public static Validation parseAttributeHeader(ChannelBuffer cb) {

        boolean firstBit;
        boolean secondBit;
        boolean thirdBit;
        boolean fourthBit;
        boolean isShort;
        byte flags = cb.readByte();
        byte typeCode = cb.readByte();
        byte temp = flags;
        //first Bit : Optional (1) or well-known (0)
        firstBit = ((temp & FIRST_BIT) == FIRST_BIT);
        //second Bit : Transitive (1) or non-Transitive (0)
        secondBit = ((temp & SECOND_BIT) == SECOND_BIT);
        //third Bit : partial (1) or complete (0)
        thirdBit = ((temp & THIRD_BIT) == THIRD_BIT);
        //forth Bit(Extended Length bit) : Attribute Length is 1 octects (0) or 2 octects (1)
        fourthBit = ((temp & FOURTH_BIT) == FOURTH_BIT);
        int len;
        if (fourthBit) {
            isShort = true;
            short length = cb.readShort();
            len = length;
        } else {
            isShort = false;
            byte length = cb.readByte();
            len = length;
        }
        return new Validation(firstBit, secondBit, thirdBit, fourthBit, len, isShort);
    }

    /**
     * Throws exception if length is not correct.
     *
     * @param errorCode Error code
     * @param subErrCode Sub Error Code
     * @param length erroneous length
     * @throws BgpParseException for erroneous length
     */
    public static void validateLen(byte errorCode, byte subErrCode, int length) throws BgpParseException {
        byte[] errLen = Ints.toByteArray(length);
        ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
        buffer.writeBytes(errLen);
        throw new BgpParseException(errorCode, subErrCode, buffer);
    }

    /**
     * Throws exception if type is not correct.
     *
     * @param errorCode Error code
     * @param subErrCode Sub Error Code
     * @param type erroneous type
     * @throws BgpParseException for erroneous type
     */
    public static void validateType(byte errorCode, byte subErrCode, int type) throws BgpParseException {
        byte[] errType = Ints.toByteArray(type);
        ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
        buffer.writeBytes(errType);
        throw new BgpParseException(errorCode, subErrCode, buffer);
    }

    /**
     * Convert byte array to InetAddress.
     *
     * @param length of IpAddress
     * @param cb channelBuffer
     * @return InetAddress
     */
    public static InetAddress toInetAddress(int length, ChannelBuffer cb) {
        byte[] address = new byte[length];
        cb.readBytes(address, 0, length);
        InetAddress ipAddress = null;
        try {
            ipAddress = InetAddress.getByAddress(address);
        } catch (UnknownHostException e) {
             log.info("InetAddress convertion failed");
        }
        return ipAddress;
    }

    /**
     * Returns first bit in type flags.
     *
     * @return first bit in type flags
     */
    public boolean getFirstBit() {
        return this.firstBit;
    }

    /**
     * Returns second bit in type flags.
     *
     * @return second bit in type flags
     */
    public boolean getSecondBit() {
        return this.secondBit;
    }

    /**
     * Returns third bit in type flags.
     *
     * @return third bit in type flags
     */
    public boolean getThirdBit() {
        return this.thirdBit;
    }

    /**
     * Returns fourth bit in type flags.
     *
     * @return fourth bit in type flags
     */
    public boolean getFourthBit() {
        return this.fourthBit;
    }

    /**
     * Returns attribute length.
     *
     * @return attribute length
     */
    public int getLength() {
        return this.len;
    }

    /**
     * Returns whether attribute length read in short or byte.
     *
     * @return whether attribute length read in short or byte
     */
    public boolean isShort() {
        return this.isShort;
    }

    /**
     * Converts byte array of prefix value to IpPrefix object.
     *
     * @param value byte array of prefix value
     * @param length prefix length in bits
     * @return object of IpPrefix
     */
    public static IpPrefix bytesToPrefix(byte[] value, int length) {
        if (value.length != IPV4_SIZE) {
            value = Arrays.copyOf(value, IPV4_SIZE);
        }
        IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length);
        return ipPrefix;
    }
}