/*
 * 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.ospfpacket.types;

import com.google.common.base.MoreObjects;
import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.ospf.exceptions.OspfErrorType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.protocol.util.OspfPacketType;
import org.onosproject.ospf.protocol.util.OspfParameters;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Representation of an OSPF Database Description packet.
 * Database Description packets are OSPF packet type 2.
 * These packets are exchanged when an adjacency is being initialized.
 * They describe the contents of the link-state database.
 */
public class DdPacket extends OspfPacketHeader {

    /*
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |   Version #   |       2       |         Packet length         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Router ID                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           Area ID                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |             AuType            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |         Interface MTU         |    Options    |0|0|0|0|0|I|M|MS
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     DD sequence number                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       +-                                                             -+
       |                                                               |
       +-                      An LSA Header                          -+
       |                                                               |
       +-                                                             -+
       |                                                               |
       +-                                                             -+
       |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              ...                              |
     */
    private static final Logger log = LoggerFactory.getLogger(DdPacket.class);
    private int imtu;
    private int options;
    private int ims; // initialize , more but / master slave bit
    private int isMaster;
    private int isInitialize;
    private int isMore;
    private long sequenceNo;
    private boolean isOpaqueCapable;
    private List<LsaHeader> lsaHeaderList = new ArrayList<>();

    /**
     * Creates an instance of DD packet.
     */
    public DdPacket() {
    }

    /**
     * Creates an instance of DD packet.
     *
     * @param ospfHeader OSPF header instance
     */
    public DdPacket(OspfPacketHeader ospfHeader) {
        populateHeader(ospfHeader);
    }

    /**
     * Gets is opaque capable or not.
     *
     * @return true if opaque capable else false
     */
    public boolean isOpaqueCapable() {
        return isOpaqueCapable;
    }

    /**
     * Sets is opaque capable or not.
     *
     * @param isOpaqueCapable true or false
     */
    public void setIsOpaqueCapable(boolean isOpaqueCapable) {
        this.isOpaqueCapable = isOpaqueCapable;
    }

    /**
     * Gets IMS value.
     *
     * @return IMS bits as an int value
     */
    public int ims() {
        return ims;
    }

    /**
     * Sets IMS value.
     *
     * @param ims IMS value
     */
    public void setIms(int ims) {
        this.ims = ims;
    }

    /**
     * Gets master bit value.
     *
     * @return 1 if master else 0
     */
    public int isMaster() {
        return isMaster;
    }

    /**
     * Sets master value.
     *
     * @param isMaster 1 represents master
     */
    public void setIsMaster(int isMaster) {
        this.isMaster = isMaster;
    }

    /**
     * Gets Initialize bit value.
     *
     * @return 1 if initialize else 0
     */
    public int isInitialize() {
        return isInitialize;
    }

    /**
     * Sets initialize value.
     *
     * @param isInitialize 1 is initialize else 0
     */
    public void setIsInitialize(int isInitialize) {
        this.isInitialize = isInitialize;
    }

    /**
     * Gets is more bit set or not.
     *
     * @return 1 if more set else 0
     */
    public int isMore() {
        return isMore;
    }

    /**
     * Sets more bit value to 0 or 1.
     *
     * @param isMore 1 if more set else 0
     */
    public void setIsMore(int isMore) {
        this.isMore = isMore;
    }


    /**
     * Gets IMTU value.
     *
     * @return IMTU value
     */
    public int imtu() {
        return imtu;
    }

    /**
     * Sets IMTU value.
     *
     * @param imtu value
     */
    public void setImtu(int imtu) {
        this.imtu = imtu;
    }

    /**
     * Gets options value.
     *
     * @return options
     */
    public int options() {
        return options;
    }

    /**
     * Sets options value.
     *
     * @param options options value
     */
    public void setOptions(int options) {
        this.options = options;
    }

    /**
     * Gets sequence number.
     *
     * @return sequenceNo
     */
    public long sequenceNo() {
        return sequenceNo;
    }

    /**
     * Sets Sequence number.
     *
     * @param sequenceNo sequence number
     */
    public void setSequenceNo(long sequenceNo) {
        this.sequenceNo = sequenceNo;
    }

    /**
     * Gets LSA header list.
     *
     * @return LSA header
     */
    public List<LsaHeader> getLsaHeaderList() {
        return lsaHeaderList;
    }

    /**
     * Adds LSA header to header list.
     *
     * @param lsaHeader lsa header instance
     */
    public void addLsaHeader(LsaHeader lsaHeader) {

        if (!lsaHeaderList.contains(lsaHeader)) {
            lsaHeaderList.add(lsaHeader);
        }
    }

    @Override
    public OspfPacketType ospfMessageType() {
        return OspfPacketType.DD;
    }

    @Override
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {

        try {
            this.setImtu(channelBuffer.readShort());

            int options = channelBuffer.readByte();
            String obit = Integer.toHexString(options);
            if (obit.length() == 1) {
                obit = "0" + obit;
            }
            String toBinary = Integer.toBinaryString(Integer.parseInt(new Character(obit.charAt(0)).toString()));
            if (toBinary.length() == 1) {
                toBinary = "000" + toBinary;
            } else if (toBinary.length() == 2) {
                toBinary = "00" + toBinary;
            } else if (toBinary.length() == 3) {
                toBinary = "0" + toBinary;
            }
            if (Integer.parseInt(new Character(toBinary.charAt(1)).toString()) == 1) {
                this.setIsOpaqueCapable(true);
            }
            this.setOptions(options);
            this.setIms(channelBuffer.readByte());
            //Convert the byte to ims bits
            String strIms = Integer.toBinaryString(this.ims());
            if (strIms.length() == 3) {
                this.setIsInitialize(Integer.parseInt(Character.toString(strIms.charAt(0))));
                this.setIsMore(Integer.parseInt(Character.toString(strIms.charAt(1))));
                this.setIsMaster(Integer.parseInt(Character.toString(strIms.charAt(2))));
            } else if (strIms.length() == 2) {
                this.setIsInitialize(0);
                this.setIsMore(Integer.parseInt(Character.toString(strIms.charAt(0))));
                this.setIsMaster(Integer.parseInt(Character.toString(strIms.charAt(1))));
            } else if (strIms.length() == 1) {
                this.setIsInitialize(0);
                this.setIsMore(0);
                this.setIsMaster(Integer.parseInt(Character.toString(strIms.charAt(0))));
            }
            this.setSequenceNo(channelBuffer.readInt());

            //add all the LSA Headers - header is of 20 bytes
            while (channelBuffer.readableBytes() >= OspfUtil.LSA_HEADER_LENGTH) {
                LsaHeader header = OspfUtil.readLsaHeader(channelBuffer.readBytes(OspfUtil.LSA_HEADER_LENGTH));
                //add the LSAHeader to DDPacket
                addLsaHeader(header);
            }

        } catch (Exception e) {
            log.debug("Error::DdPacket:: {}", e.getMessage());
            throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
        }
    }

    @Override
    public byte[] asBytes() {

        byte[] ddMessage = null;

        byte[] ddHeader = getDdHeaderAsByteArray();
        byte[] ddBody = getDdBodyAsByteArray();
        ddMessage = Bytes.concat(ddHeader, ddBody);

        return ddMessage;
    }

    /**
     * Gets DD Header as byte array.
     *
     * @return dd header as byte array.
     */
    public byte[] getDdHeaderAsByteArray() {
        List<Byte> headerLst = new ArrayList<>();

        try {
            headerLst.add((byte) this.ospfVersion());
            headerLst.add((byte) this.ospfType());
            headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.ospfPacLength())));
            headerLst.addAll(Bytes.asList(this.routerId().toOctets()));
            headerLst.addAll(Bytes.asList(this.areaId().toOctets()));
            headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.checksum())));
            headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.authType())));
            //Authentication is 0 always. Total 8 bytes consist of zero
            byte[] auth = new byte[OspfUtil.EIGHT_BYTES];
            headerLst.addAll(Bytes.asList(auth));

        } catch (Exception e) {
            log.debug("Error");

        }

        return Bytes.toArray(headerLst);
    }


    /**
     * Gets DD body as byte array.
     *
     * @return DD body
     */
    public byte[] getDdBodyAsByteArray() {
        List<Byte> bodyLst = new ArrayList<>();

        try {
            bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.imtu())));
            bodyLst.add((byte) this.options());

            StringBuilder sb = new StringBuilder();
            sb.append(this.isInitialize());
            sb.append(this.isMore());
            sb.append(this.isMaster());

            bodyLst.add((byte) Integer.parseInt(sb.toString(), 2));
            bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(this.sequenceNo()))); // passing long value

            for (LsaHeader lsaHeader : lsaHeaderList) {
                if (lsaHeader.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
                        lsaHeader.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
                        lsaHeader.lsType() == OspfParameters.AS_OPAQUE_LSA) {
                    OpaqueLsaHeader header = (OpaqueLsaHeader) lsaHeader;
                    bodyLst.addAll(Bytes.asList(header.getOpaqueLsaHeaderAsByteArray()));
                } else {
                    bodyLst.addAll(Bytes.asList(lsaHeader.getLsaHeaderAsByteArray()));
                }
            }
        } catch (Exception e) {
            log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(bodyLst);
        }

        return Bytes.toArray(bodyLst);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("imtu", imtu)
                .add("options", options)
                .add("ims", ims)
                .add("isMaster", isMaster)
                .add("isInitialize", isInitialize)
                .add("isMore", isMore)
                .add("sequenceNo", sequenceNo)
                .add("isOpaqueCapable", isOpaqueCapable)
                .add("lsaHeaderList", lsaHeaderList)
                .toString();
    }
}