/*
 * Copyright 2016 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.ospf.protocol.util;

import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.DatatypeConverter;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

/**
 * Representation of an OSPF constants and utility methods.
 */
public final class OspfUtil {

    public static final int OSPF_VERSION_2 = 2;
    public static final int OSPF_VERSION = OSPF_VERSION_2;
    public static final int PACKET_MINIMUM_LENGTH = 24;
    public static final int OSPF_HEADER_LENGTH = 24;
    public static final int LSA_HEADER_LENGTH = 20;
    public static final int DD_HEADER_LENGTH = OSPF_HEADER_LENGTH + 8;
    public static final int LSREQUEST_LENGTH = 12;
    public static final int OSPFPACKET_LENGTH_POS1 = 2;
    public static final int OSPFPACKET_LENGTH_POS2 = 3;
    public static final int OSPFPACKET_CHECKSUM_POS1 = 12;
    public static final int OSPFPACKET_CHECKSUM_POS2 = 13;
    public static final int LSAPACKET_CHECKSUM_POS1 = 16;
    public static final int LSAPACKET_CHECKSUM_POS2 = 17;
    public static final Ip4Address ALL_SPF_ROUTERS = Ip4Address.valueOf("224.0.0.5");
    public static final Ip4Address ALL_DROUTERS = Ip4Address.valueOf("224.0.0.6");
    public static final int ONLY_ALL_SPF_ROUTERS = 1;
    public static final int JOIN_ALL_DROUTERS = 2;
    public static final int INITIALIZE_SET = 1;
    public static final int INITIALIZE_NOTSET = 0;
    public static final int MORE_SET = 1;
    public static final int MORE_NOTSET = 0;
    public static final int IS_MASTER = 1;
    public static final int NOT_MASTER = 0;
    public static final int NOT_ASSIGNED = 0;
    public static final int FOUR_BYTES = 4;
    public static final int EIGHT_BYTES = 8;
    public static final int TWELVE_BYTES = 12;
    public static final int EXTERNAL_DESTINATION_LENGTH = 12;
    private static final Logger log =
            LoggerFactory.getLogger(OspfUtil.class);

    /**
     * Creates an instance.
     */
    private OspfUtil() {

    }

    /**
     * Checks given IPs are in same network or not.
     *
     * @param ip1  IP address
     * @param ip2  IP address
     * @param mask network mask
     * @return true if both are in same network else false
     * @throws Exception might throws exception while parsing ip address
     */
    public static boolean sameNetwork(Ip4Address ip1, Ip4Address ip2, Ip4Address mask)
            throws Exception {

        byte[] a1 = ip1.toOctets();
        byte[] a2 = ip2.toOctets();
        byte[] m = mask.toOctets();

        for (int i = 0; i < a1.length; i++) {
            if ((a1[i] & m[i]) != (a2[i] & m[i])) {
                return false;
            }
        }

        return true;
    }

    /**
     * Converts IP address to long.
     *
     * @param ipAddress IP address
     * @return long value represents IP address
     */
    public static long ipAddressToLong(String ipAddress) {
        StringTokenizer st = new StringTokenizer(ipAddress, ".");
        long ipAsNumber = Long.parseLong(st.nextToken()) * (long) Math.pow(256, 3);
        ipAsNumber += Long.parseLong(st.nextToken()) * (long) Math.pow(256, 2);
        ipAsNumber += Long.parseLong(st.nextToken()) * 256;
        ipAsNumber += +Long.parseLong(st.nextToken());

        return ipAsNumber;
    }

    /**
     * Checks option field to see whether opaque enabled or not.
     * 2nd Bit in options field of DdPacket represents Opaque.
     * 7th bit is external capability.
     * This method checks Opaque bit is set in the options or not.
     *
     * @param options options value
     * @return true if opaque enabled else false.
     */
    public static boolean isOpaqueEnabled(int options) {
        Boolean[] bits = new Boolean[8];
        for (int i = 7; i >= 0; i--) {
            bits[i] = (options & (1 << i)) != 0;
        }

        List<Boolean> list = Arrays.asList(bits);
        Collections.reverse(list);

        //2nd bit is Opaque.
        return list.get(1);
    }

    /**
     * Converts a byte to integer variable.
     *
     * @param bytesToConvert bytes to convert
     * @return integer representation of bytes
     */
    public static int byteToInteger(byte[] bytesToConvert) {
        final StringBuilder builder = new StringBuilder();
        for (byte eachByte : bytesToConvert) {
            builder.append(String.format("%02x", eachByte));
        }
        int num = Integer.parseInt(builder.toString(), 16);
        return num;
    }

    /**
     * Converts a byte to long variable.
     *
     * @param bytesToConvert bytes to convert
     * @return long representation of bytes
     */
    public static long byteToLong(byte[] bytesToConvert) {
        final StringBuilder builder = new StringBuilder();
        for (byte eachByte : bytesToConvert) {
            builder.append(String.format("%02x", eachByte));
        }
        long num = Long.parseLong(builder.toString(), 16);
        return num;
    }

    /**
     * Creates a random number.
     *
     * @return random number
     */
    public static int createRandomNumber() {
        Random rnd = new Random();
        int randomNumber = 10000000 + rnd.nextInt(90000000);
        return randomNumber;
    }

    /**
     * Reads the LSA header from channel buffer.
     *
     * @param channelBuffer channel buffer instance
     * @return LSA header instance.
     * @throws Exception might throws exception while parsing buffer
     */
    public static LsaHeader readLsaHeader(ChannelBuffer channelBuffer) throws Exception {
        //add all the LSA Headers - one header is of 20 bytes
        LsaHeader lsaHeader = null;
        if (channelBuffer.readableBytes() >= OspfUtil.LSA_HEADER_LENGTH) {
            byte[] byteArray = new byte[OspfUtil.FOUR_BYTES];
            channelBuffer.readBytes(byteArray, 0, OspfUtil.FOUR_BYTES);
            ChannelBuffer tempBuffer = ChannelBuffers.copiedBuffer(byteArray);
            int lsType = byteArray[3];
            if (lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA || lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA
                    || lsType == OspfParameters.AS_OPAQUE_LSA) {
                OpaqueLsaHeader header = new OpaqueLsaHeader();
                header.setAge(tempBuffer.readShort());
                header.setOptions(tempBuffer.readByte());
                header.setLsType(tempBuffer.readByte());
                header.setOpaqueType(channelBuffer.readByte());
                header.setOpaqueId(channelBuffer.readUnsignedMedium());
                byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                header.setAdvertisingRouter(Ip4Address.valueOf(tempByteArray));
                header.setLsSequenceNo(channelBuffer.readInt());
                header.setLsCheckSum(channelBuffer.readUnsignedShort());
                header.setLsPacketLen(channelBuffer.readShort());
                byte[] opaqueIdBytes = OspfUtil.convertToTwoBytes(header.opaqueId());
                header.setLinkStateId(header.opaqueType() + "." + "0" + "." +
                                              opaqueIdBytes[0] + "." + opaqueIdBytes[1]);
                lsaHeader = header;
            } else {
                LsaHeader header = new LsaHeader();
                header.setAge(tempBuffer.readShort());
                header.setOptions(tempBuffer.readByte());
                header.setLsType(tempBuffer.readByte());
                byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                header.setLinkStateId(InetAddress.getByAddress(tempByteArray).getHostName());
                tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                header.setAdvertisingRouter(Ip4Address.valueOf(tempByteArray));
                header.setLsSequenceNo(channelBuffer.readInt());
                header.setLsCheckSum(channelBuffer.readUnsignedShort());
                header.setLsPacketLen(channelBuffer.readShort());
                lsaHeader = header;
            }
        }
        return lsaHeader;
    }


    /**
     * Converts an integer to two bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToTwoBytes(int numberToConvert) {

        byte[] numInBytes = new byte[2];
        String s1 = Integer.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
        }
        return numInBytes;
    }

    /**
     * Converts a number to three bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToThreeBytes(int numberToConvert) {
        byte[] numInBytes = new byte[3];
        String s1 = Integer.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = hexas[0];
        } else if (hexas.length == 2) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
            numInBytes[2] = hexas[1];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
            numInBytes[2] = hexas[2];
        }
        return numInBytes;
    }

    /**
     * Converts a number to four bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToFourBytes(int numberToConvert) {

        byte[] numInBytes = new byte[4];
        String s1 = Integer.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = 0;
            numInBytes[3] = hexas[0];
        } else if (hexas.length == 2) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = hexas[0];
            numInBytes[3] = hexas[1];
        } else if (hexas.length == 3) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
            numInBytes[2] = hexas[1];
            numInBytes[3] = hexas[2];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
            numInBytes[2] = hexas[2];
            numInBytes[3] = hexas[3];
        }
        return numInBytes;
    }

    /**
     * Converts a number to four bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToFourBytes(long numberToConvert) {

        byte[] numInBytes = new byte[4];
        String s1 = Long.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        if (s1.length() == 16) {
            s1 = s1.substring(8, s1.length());
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = 0;
            numInBytes[3] = hexas[0];
        } else if (hexas.length == 2) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = hexas[0];
            numInBytes[3] = hexas[1];
        } else if (hexas.length == 3) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
            numInBytes[2] = hexas[1];
            numInBytes[3] = hexas[2];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
            numInBytes[2] = hexas[2];
            numInBytes[3] = hexas[3];
        }
        return numInBytes;
    }

    /**
     * Adds the checksum and length in packet.
     *
     * @param ospfPacket       ospf packet
     * @param lengthBytePos1   length byte position
     * @param lengthBytePos2   length byte position
     * @param checksumBytePos1 checksum byte position
     * @param checksumBytePos2 checksum byte position
     * @return byte array with checksum and length
     */
    public static byte[] addLengthAndCheckSum(byte[] ospfPacket, int lengthBytePos1, int lengthBytePos2,
                                              int checksumBytePos1, int checksumBytePos2) {
        //Set the length of the packet
        //Get the total length of the packet
        int length = ospfPacket.length;
        //Convert the lenth to two bytes as the length field is 2 bytes
        byte[] lenthInTwoBytes = OspfUtil.convertToTwoBytes(length);
        //ospf header 3rd and 4th position represents length
        ospfPacket[lengthBytePos1] = lenthInTwoBytes[0]; //assign 1st byte in lengthBytePos1
        ospfPacket[lengthBytePos2] = lenthInTwoBytes[1]; //assign 2st byte in lengthBytePos2

        //Get the checksum as two bytes.
        byte[] checkSumInTwoBytes = new ChecksumCalculator().calculateOspfCheckSum(ospfPacket,
                                                                                   checksumBytePos1, checksumBytePos2);
        ospfPacket[checksumBytePos1] = checkSumInTwoBytes[0]; //assign 1st byte in checksumBytePos1
        ospfPacket[checksumBytePos2] = checkSumInTwoBytes[1]; //assign 2st byte in checksumBytePos2

        return ospfPacket;
    }

    /**
     * Adds metadata to ospf packet like whether to join multi cast group and destination IP.
     *
     * @param ospfPacket       OSPF packet
     * @param allDroutersValue whether to join multi cast or not
     * @param destinationIp    destination ip address
     * @return byte array
     */
    public static byte[] addMetadata(byte[] ospfPacket, int allDroutersValue, Ip4Address destinationIp) {
        byte[] packet;
        byte[] allDroutersByteVal = {(byte) allDroutersValue};
        byte[] destIpAsBytes = destinationIp.toOctets();
        byte[] metadata = Bytes.concat(allDroutersByteVal, destIpAsBytes);

        packet = Bytes.concat(metadata, ospfPacket);

        return packet;
    }
}