/*
 * 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.controller.OspfLsa;
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.lsa.types.AsbrSummaryLsa;
import org.onosproject.ospf.protocol.lsa.types.ExternalLsa;
import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10;
import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa11;
import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa9;
import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
import org.onosproject.ospf.protocol.lsa.types.SummaryLsa;
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.LinkedList;
import java.util.List;

/**
 * Representation of an OSPF Link State Update packet.
 * Link State Update packets are OSPF packet type 4.  These packets
 * implement the flooding of LSAs.  Each Link State Update packet
 * carries a collection of LSAs one hop further from their origin.
 * Several LSAs may be included in a single packet.
 */
public class LsUpdate 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 #   |       4       |         Packet length         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Router ID                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           Area ID                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |             AuType            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            # LSAs                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       +-                                                            +-+
       |                             LSAs                              |
       +-                                                            +-+
       |                              ...                              |
     */
    private static final Logger log = LoggerFactory.getLogger(LsUpdate.class);
    private int numberOfLsa;
    private List<OspfLsa> lsaList = new LinkedList<>();

    /**
     * Creates an instance of Link State Update packet.
     */
    public LsUpdate() {
    }

    /**
     * Creates an instance of Link State Update packet.
     *
     * @param ospfHeader ospf header instance.
     */
    public LsUpdate(OspfPacketHeader ospfHeader) {
        populateHeader(ospfHeader);
    }

    /**
     * Gets the LSA list.
     *
     * @return list of LSA
     */
    public List getLsaList() {
        return lsaList;
    }

    /**
     * Adds the LSA to list.
     *
     * @param lsa LSA
     */
    public void addLsa(OspfLsa lsa) {
        if (!lsaList.contains(lsa)) {
            lsaList.add(lsa);
        }
    }

    /**
     * Gets the number of LSA.
     *
     * @return number of LSA
     */
    public int noLsa() {
        return numberOfLsa;
    }

    /**
     * Sets number of LSA.
     *
     * @param numberOfLsa number of LSA
     */
    public void setNumberOfLsa(int numberOfLsa) {
        this.numberOfLsa = numberOfLsa;
    }


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

    @Override
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
        try {
            //From header 4 bytes is number of lsa's
            this.setNumberOfLsa(channelBuffer.readInt());
            //get the remaining bytes represents Number of LSA's present. Add all the LSA's
            while (channelBuffer.readableBytes() > OspfUtil.LSA_HEADER_LENGTH) {

                LsaHeader header = OspfUtil.readLsaHeader(channelBuffer.readBytes(OspfUtil.LSA_HEADER_LENGTH));
                int lsaLength = header.lsPacketLen();
                int lsType = header.lsType();

                switch (lsType) {
                    case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
                        OpaqueLsa9 opaqueLsa9 = new OpaqueLsa9((OpaqueLsaHeader) header);
                        opaqueLsa9.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(opaqueLsa9);
                        break;
                    case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
                        OpaqueLsa10 opaqueLsa10 = new OpaqueLsa10((OpaqueLsaHeader) header);
                        opaqueLsa10.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(opaqueLsa10);
                        break;
                    case OspfParameters.AS_OPAQUE_LSA:
                        OpaqueLsa11 opaqueLsa11 = new OpaqueLsa11((OpaqueLsaHeader) header);
                        opaqueLsa11.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(opaqueLsa11);
                        break;
                    case OspfParameters.ROUTER:
                        RouterLsa routerLsa = new RouterLsa(header);
                        routerLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(routerLsa);
                        break;
                    case OspfParameters.NETWORK:
                        NetworkLsa networkLsa = new NetworkLsa(header);
                        networkLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(networkLsa);
                        break;
                    case OspfParameters.ASBR_SUMMARY:
                        AsbrSummaryLsa asbrSummaryLsa = new AsbrSummaryLsa(header);
                        asbrSummaryLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(asbrSummaryLsa);
                        break;
                    case OspfParameters.SUMMARY:
                        SummaryLsa summaryLSA = new SummaryLsa(header);
                        summaryLSA.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(summaryLSA);
                        break;
                    case OspfParameters.EXTERNAL_LSA:
                        ExternalLsa externalLsa = new ExternalLsa(header);
                        externalLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(externalLsa);
                        break;
                    default:
                        log.debug("LSUpdate::readLsUpdateBody::UnKnown LS Type: {}", lsType);
                        break;
                }
            }
        } catch (Exception e) {
            log.debug("Error::LsUpdate:: {}", e.getMessage());
            throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
        }
    }

    @Override
    public byte[] asBytes() {
        byte[] lsuMessage = null;

        byte[] ospfHeader = getLsuHeaderAsByteArray();
        byte[] lsuBody = getLsuBodyAsByteArray();
        lsuMessage = Bytes.concat(ospfHeader, lsuBody);

        return lsuMessage;
    }

    /**
     * Gets lsu header.
     *
     * @return lsu header as byte array
     */
    public byte[] getLsuHeaderAsByteArray() {
        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::LSUpdate::getLsuHeaderAsByteArray:: {}", e.getMessage());
            return Bytes.toArray(headerLst);
        }

        return Bytes.toArray(headerLst);
    }

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

        try {
            //add number of LSA's
            bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(this.noLsa())));
            //for each type of LSA's from the list get lsa bytes
            for (OspfLsa ospfLsa : lsaList) {
                //Check the type of lsa and build bytes accordingly
                switch (ospfLsa.getOspfLsaType().value()) {
                    case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
                        OpaqueLsa9 opaqueLsa9 = (OpaqueLsa9) ospfLsa;
                        bodyLst.addAll(Bytes.asList(opaqueLsa9.asBytes()));
                        break;
                    case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
                        OpaqueLsa10 opaqueLsa10 = (OpaqueLsa10) ospfLsa;
                        bodyLst.addAll(Bytes.asList(opaqueLsa10.asBytes()));
                        break;
                    case OspfParameters.AS_OPAQUE_LSA:
                        OpaqueLsa11 opaqueLsa11 = (OpaqueLsa11) ospfLsa;
                        bodyLst.addAll(Bytes.asList(opaqueLsa11.asBytes()));
                        break;
                    case OspfParameters.ROUTER:
                        RouterLsa routerLsa = (RouterLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(routerLsa.asBytes()));
                        break;
                    case OspfParameters.NETWORK:
                        NetworkLsa networkLsa = (NetworkLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(networkLsa.asBytes()));
                        break;
                    case OspfParameters.ASBR_SUMMARY:
                        AsbrSummaryLsa asbrSummaryLsa = (AsbrSummaryLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(asbrSummaryLsa.asBytes()));
                        break;
                    case OspfParameters.SUMMARY:
                        SummaryLsa summaryLsa = (SummaryLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(summaryLsa.asBytes()));
                        break;
                    case OspfParameters.EXTERNAL_LSA:
                        ExternalLsa externalLsa = (ExternalLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(externalLsa.asBytes()));
                        break;
                    default:
                        log.debug("LSUpdate::getLsuBodyAsByteArray::UnKnown ospfLsa: {}", ospfLsa);
                        break;
                }
            }

        } catch (Exception e) {
            log.debug("Error::getLsuBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(bodyLst);
        }

        return Bytes.toArray(bodyLst);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("noLsa", numberOfLsa)
                .add("lsaList", lsaList)
                .toString();
    }
}