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

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
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.subtypes.OspfLsaLink;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

/**
 * Representation of a Router LSA, and the fields and methods to access them.
 */
public class RouterLsa extends LsaHeader {
    /*
        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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |            LS age             |     Options   |       1       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                        Link State ID                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     Advertising Router                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     LS sequence number                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |         LS checksum           |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |    0    |V|E|B|        0      |            # links            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Link ID                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         Link Data                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |     Type      |     # TOS     |            metric             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              ...                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |      TOS      |        0      |          TOS  metric          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Link ID                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         Link Data                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              ...                              |
     */
    private static final Logger log =
            LoggerFactory.getLogger(RouterLsa.class);
    private boolean isVirtualEndPoint;
    private boolean isAsBoundaryRouter;
    private boolean isAreaBorderRouter;
    private int noLink;
    private List<OspfLsaLink> routerLinks = new ArrayList<>();

    /**
     * Creates an instance of Router LSA.
     */
    public RouterLsa() {
    }

    /**
     * Creates an instance of Router LSA.
     *
     * @param lsaHeader lsa header instance
     */
    public RouterLsa(LsaHeader lsaHeader) {
        populateHeader(lsaHeader);
    }

    /**
     * Sets virtual endpoint or not.
     *
     * @param isVirtualEndPoint true or false
     */
    public void setVirtualEndPoint(boolean isVirtualEndPoint) {
        this.isVirtualEndPoint = isVirtualEndPoint;
    }

    /**
     * Sets if it is an AS boundary router or not.
     *
     * @param isAsBoundaryRouter true if AS boundary router else false
     */
    public void setAsBoundaryRouter(boolean isAsBoundaryRouter) {
        this.isAsBoundaryRouter = isAsBoundaryRouter;
    }

    /**
     * Sets whether it is an ABR or not.
     *
     * @param isAreaBorderRouter true if ABR else false
     */
    public void setAreaBorderRouter(boolean isAreaBorderRouter) {
        this.isAreaBorderRouter = isAreaBorderRouter;
    }

    /**
     * Gets number of links.
     *
     * @return number of links
     */
    public int noLink() {
        return noLink;
    }

    /**
     * Sets number of links.
     *
     * @param noLink number of links
     */
    public void setNoLink(int noLink) {
        this.noLink = noLink;
    }


    /**
     * Adds router link.
     *
     * @param lsaLink LSA link
     */
    public void addRouterLink(OspfLsaLink lsaLink) {
        if (!this.routerLinks.contains(lsaLink)) {
            this.routerLinks.add(lsaLink);
        }
    }

    /**
     * Gets router link.
     *
     * @return routerLinks LSA link list
     */
    public List<OspfLsaLink> routerLink() {
        return this.routerLinks;
    }

    /**
     * Reads from channel buffer and populate this.
     *
     * @param channelBuffer channelBuffer instance.
     * @throws OspfParseException might throws exception while parsing buffer
     */
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {

        try {
            int veb = channelBuffer.readByte();
            int unUsed = channelBuffer.readByte();
            //Convert the byte to veb bits
            String strVeb = Integer.toBinaryString(veb);
            if (strVeb.length() == 3) {
                this.setVirtualEndPoint((Integer.parseInt(Character.toString(strVeb.charAt(0))) == 1) ? true : false);
                this.setAsBoundaryRouter((Integer.parseInt(Character.toString(strVeb.charAt(1))) == 1) ? true : false);
                this.setAreaBorderRouter((Integer.parseInt(Character.toString(strVeb.charAt(2))) == 1) ? true : false);
            } else if (strVeb.length() == 2) {
                this.setVirtualEndPoint(false);
                this.setAsBoundaryRouter((Integer.parseInt(Character.toString(strVeb.charAt(0))) == 1) ? true : false);
                this.setAreaBorderRouter((Integer.parseInt(Character.toString(strVeb.charAt(1))) == 1) ? true : false);
            } else if (strVeb.length() == 1) {
                this.setVirtualEndPoint(false);
                this.setAsBoundaryRouter(false);
                this.setAreaBorderRouter((Integer.parseInt(Character.toString(strVeb.charAt(0))) == 1) ? true : false);
            }
            this.setNoLink(channelBuffer.readUnsignedShort());
            while (channelBuffer.readableBytes() >= OspfUtil.TWELVE_BYTES) {
                OspfLsaLink ospfLsaLink = new OspfLsaLink();

                byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                ospfLsaLink.setLinkId(InetAddress.getByAddress(tempByteArray).getHostName());
                tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                ospfLsaLink.setLinkData(InetAddress.getByAddress(tempByteArray).getHostName());
                ospfLsaLink.setLinkType(channelBuffer.readByte());
                ospfLsaLink.setTos(channelBuffer.readByte());
                ospfLsaLink.setMetric(channelBuffer.readUnsignedShort());
                //add the link
                this.addRouterLink(ospfLsaLink);
            }
        } catch (Exception e) {
            log.debug("Error::RouterLsa:: {}", e.getMessage());
            throw new OspfParseException(OspfErrorType.OSPF_MESSAGE_ERROR, OspfErrorType.BAD_MESSAGE);
        }
    }

    /**
     * Returns instance as bytes.
     *
     * @return instance as bytes
     * @throws OspfParseException might throws exception while parsing packet
     */
    public byte[] asBytes() throws OspfParseException {
        byte[] lsaMessage = null;

        byte[] lsaHeader = getLsaHeaderAsByteArray();
        byte[] lsaBody = getLsaBodyAsByteArray();
        lsaMessage = Bytes.concat(lsaHeader, lsaBody);

        return lsaMessage;
    }

    /**
     * Gets the LSA body as bytes.
     *
     * @return LSA body as bytes
     */
    public byte[] getLsaBodyAsByteArray() {
        List<Byte> bodyLst = new ArrayList<>();

        try {
            int isVirtualEndPointVal = this.isVirtualEndPoint ? 1 : 0;
            int isASBoundaryRouterVal = this.isAsBoundaryRouter ? 1 : 0;
            int isAreaBorderRouterVal = this.isAreaBorderRouter ? 1 : 0;

            StringBuilder sb = new StringBuilder();
            sb.append(Integer.toBinaryString(isVirtualEndPointVal));
            sb.append(Integer.toBinaryString(isASBoundaryRouterVal));
            sb.append(Integer.toBinaryString(isAreaBorderRouterVal));

            //added VEB
            bodyLst.add((byte) Integer.parseInt(sb.toString(), 2));
            //second byte is 0.
            bodyLst.add((byte) 0);
            //Number of links
            bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.noLink())));

            //add each link details
            for (OspfLsaLink lsaLink : routerLinks) {
                bodyLst.addAll(Bytes.asList(InetAddress.getByName(lsaLink.linkId()).getAddress()));
                bodyLst.addAll(Bytes.asList(InetAddress.getByName(lsaLink.linkData()).getAddress()));
                bodyLst.add((byte) lsaLink.linkType());
                bodyLst.add((byte) lsaLink.tos());
                bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(lsaLink.metric())));
            }
        } catch (Exception e) {
            log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(bodyLst);
        }

        return Bytes.toArray(bodyLst);
    }

    /**
     * Increment the link by 1.
     */
    public void incrementLinkNo() {
        this.noLink++;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("isVirtualEndPoint", isVirtualEndPoint)
                .add("isAsBoundaryRouter", isAsBoundaryRouter)
                .add("isAreaBorderRouter", isAreaBorderRouter)
                .add("noLink", noLink)
                .add("routerLinks", routerLinks)
                .toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        RouterLsa that = (RouterLsa) o;
        return Objects.equal(isVirtualEndPoint, that.isVirtualEndPoint) &&
                Objects.equal(isAsBoundaryRouter, that.isAsBoundaryRouter) &&
                Objects.equal(isAreaBorderRouter, that.isAreaBorderRouter) &&
                Objects.equal(noLink, that.noLink) &&
                Objects.equal(routerLinks, that.routerLinks);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(isVirtualEndPoint, isAsBoundaryRouter, isAreaBorderRouter,
                                noLink, routerLinks);
    }
}