/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.pcep.server.impl;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.LinkedList;

import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
import org.onosproject.incubator.net.resource.label.LabelResource;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.incubator.net.resource.label.LabelResourceService;
import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.pcelabelstore.DefaultLspLocalLabelInfo;
import org.onosproject.pcelabelstore.PcepLabelOp;
import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
import org.onosproject.pcelabelstore.api.PceLabelStore;
import org.onosproject.pcep.server.LspType;
import org.onosproject.pcep.server.PccId;
import org.onosproject.pcep.server.PcepAnnotationKeys;
import org.onosproject.pcep.server.PcepClient;
import org.onosproject.pcep.server.PcepClientController;
import org.onosproject.pcep.server.SrpIdGenerators;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepAttribute;
import org.onosproject.pcepio.protocol.PcepBandwidthObject;
import org.onosproject.pcepio.protocol.PcepEroObject;
import org.onosproject.pcepio.protocol.PcepLabelObject;
import org.onosproject.pcepio.protocol.PcepLabelUpdate;
import org.onosproject.pcepio.protocol.PcepLabelUpdateMsg;
import org.onosproject.pcepio.protocol.PcepLspObject;
import org.onosproject.pcepio.protocol.PcepMsgPath;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepUpdateMsg;
import org.onosproject.pcepio.protocol.PcepUpdateRequest;
import org.onosproject.pcepio.types.IPv4SubObject;
import org.onosproject.pcepio.types.NexthopIPv4addressTlv;
import org.onosproject.pcepio.types.PathSetupTypeTlv;
import org.onosproject.pcepio.types.PcepLabelDownload;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
import org.onosproject.pcepio.types.SymbolicPathNameTlv;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

import static org.onosproject.pcep.server.PcepAnnotationKeys.BANDWIDTH;
import static org.onosproject.pcep.server.PcepAnnotationKeys.LSP_SIG_TYPE;
import static org.onosproject.pcep.server.PcepAnnotationKeys.PCE_INIT;
import static org.onosproject.pcep.server.PcepAnnotationKeys.DELEGATE;

/**
 * Basic PCECC handler.
 * In Basic PCECC, after path computation will configure IN and OUT label to nodes.
 * [X]OUT---link----IN[Y]OUT---link-----IN[Z] where X, Y and Z are nodes.
 * For generating labels, will go thorough links in the path from Egress to Ingress.
 * In each link, will take label from destination node local pool as IN label,
 * and assign this label as OUT label to source node.
 */
public final class BasicPceccHandler {
    private static final Logger log = LoggerFactory.getLogger(BasicPceccHandler.class);
    public static final int OUT_LABEL_TYPE = 0;
    public static final int IN_LABEL_TYPE = 1;
    public static final long IDENTIFIER_SET = 0x100000000L;
    public static final long SET = 0xFFFFFFFFL;
    private static final String LSRID = "lsrId";
    private static final String LABEL_RESOURCE_SERVICE_NULL = "Label Resource Service cannot be null";
    private static final String PCE_STORE_NULL = "PCE Store cannot be null";
    private static BasicPceccHandler crHandlerInstance = null;
    private LabelResourceService labelRsrcService;
    private DeviceService deviceService;
    private PceLabelStore pceStore;
    private PcepClientController clientController;
    private PcepLabelObject labelObj;

    /**
     * Initializes default values.
     */
    private BasicPceccHandler() {
    }

    /**
     * Returns single instance of this class.
     *
     * @return this class single instance
     */
    public static BasicPceccHandler getInstance() {
        if (crHandlerInstance == null) {
            crHandlerInstance = new BasicPceccHandler();
        }
        return crHandlerInstance;
    }

    /**
     * Initialization of label manager and pce store.
     *
     * @param labelRsrcService label resource service
     * @param deviceService device service
     * @param pceStore pce label store
     * @param clientController client controller
     */
    public void initialize(LabelResourceService labelRsrcService,
                           DeviceService deviceService,
                           PceLabelStore pceStore,
                           PcepClientController clientController) {
        this.labelRsrcService = labelRsrcService;
        this.deviceService = deviceService;
        this.pceStore = pceStore;
        this.clientController = clientController;
    }

    /**
     * Allocates labels from local resource pool and configure these (IN and OUT) labels into devices.
     *
     * @param tunnel tunnel between ingress to egress
     * @return success or failure
     */
    public boolean allocateLabel(Tunnel tunnel) {
        long applyNum = 1;
        boolean isLastLabelToPush = false;
        Collection<LabelResource> labelRscList;

        checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
        checkNotNull(pceStore, PCE_STORE_NULL);

        List<Link> linkList = tunnel.path().links();
        if ((linkList != null) && (!linkList.isEmpty())) {
            // Sequence through reverse order to push local labels into devices
            // Generation of labels from egress to ingress
            for (ListIterator<Link> iterator = linkList.listIterator(linkList.size()); iterator.hasPrevious();) {
                Link link = iterator.previous();
                DeviceId dstDeviceId = link.dst().deviceId();
                DeviceId srcDeviceId = link.src().deviceId();
                labelRscList = labelRsrcService.applyFromDevicePool(dstDeviceId, applyNum);
                if ((labelRscList != null) && (!labelRscList.isEmpty())) {
                    // Link label value is taken from destination device local pool.
                    // [X]OUT---link----IN[Y]OUT---link-----IN[Z] where X, Y and Z are nodes.
                    // Link label value is used as OUT and IN for both ends
                    // (source and destination devices) of the link.
                    // Currently only one label is allocated to a device (destination device).
                    // So, no need to iterate through list
                    Iterator<LabelResource> labelIterator = labelRscList.iterator();
                    DefaultLabelResource defaultLabelResource = (DefaultLabelResource) labelIterator.next();
                    LabelResourceId labelId = defaultLabelResource.labelResourceId();
                    log.debug("Allocated local label: " + labelId.toString()
                              + "to device: " + defaultLabelResource.deviceId().toString());
                    PortNumber dstPort = link.dst().port();

                    // Check whether this is last link label to push
                    if (!iterator.hasPrevious()) {
                       isLastLabelToPush = true;
                    }

                    try {
                        // Push into destination device
                        // Destination device IN port is link.dst().port()
                        pushLocalLabels(dstDeviceId, labelId, dstPort, tunnel, false,
                                            Long.valueOf(LabelType.IN_LABEL.value), PcepLabelOp.ADD);

                        // Push into source device
                        // Source device OUT port will be link.dst().port(). Means its remote port used to send packet.
                        pushLocalLabels(srcDeviceId, labelId, dstPort, tunnel, isLastLabelToPush,
                                            Long.valueOf(LabelType.OUT_LABEL.value), PcepLabelOp.ADD);
                    } catch (PcepParseException e) {
                        log.error("Failed to push local label for device {} or {} for tunnel {}.",
                                  dstDeviceId.toString(), srcDeviceId.toString(), tunnel.tunnelName().toString());
                    }

                    // Add or update pcecc tunnel info in pce store.
                    updatePceccTunnelInfoInStore(srcDeviceId, dstDeviceId, labelId, dstPort,
                                                 tunnel);
                } else {
                    log.error("Unable to allocate label to device id {}.", dstDeviceId.toString());
                    releaseLabel(tunnel);
                    return false;
                }
            }
        } else {
           log.error("Tunnel {} is having empty links.", tunnel.toString());
           return false;
        }
        return true;
    }

    /**
     * Updates list of local labels of PCECC tunnel info in pce store.
     *
     * @param srcDeviceId source device in a link
     * @param dstDeviceId destination device in a link
     * @param labelId label id of a link
     * @param dstPort destination device port number of a link
     * @param tunnel tunnel
     */
    public void updatePceccTunnelInfoInStore(DeviceId srcDeviceId, DeviceId dstDeviceId, LabelResourceId labelId,
                                                PortNumber dstPort, Tunnel tunnel) {
       // First try to retrieve device from store and update its label id if it is exists,
       // otherwise add it
       boolean dstDeviceUpdated = false;
       boolean srcDeviceUpdated = false;

       List<LspLocalLabelInfo> lspLabelInfoList = pceStore.getTunnelInfo(tunnel.tunnelId());
       if ((lspLabelInfoList != null) && (!lspLabelInfoList.isEmpty())) {
           for (int i = 0; i < lspLabelInfoList.size(); ++i) {
               LspLocalLabelInfo lspLocalLabelInfo =
                       lspLabelInfoList.get(i);
               LspLocalLabelInfo.Builder lspLocalLabelInfoBuilder = null;
               if (dstDeviceId.equals(lspLocalLabelInfo.deviceId())) {
                   lspLocalLabelInfoBuilder = DefaultLspLocalLabelInfo.builder(lspLocalLabelInfo);
                   lspLocalLabelInfoBuilder.inLabelId(labelId);
                   // Destination device IN port will be link destination port
                   lspLocalLabelInfoBuilder.inPort(dstPort);
                   dstDeviceUpdated = true;
               } else if (srcDeviceId.equals(lspLocalLabelInfo.deviceId())) {
                   lspLocalLabelInfoBuilder = DefaultLspLocalLabelInfo.builder(lspLocalLabelInfo);
                   lspLocalLabelInfoBuilder.outLabelId(labelId);
                   // Source device OUT port will be link destination (remote) port
                   lspLocalLabelInfoBuilder.outPort(dstPort);
                   srcDeviceUpdated = true;
               }

               // Update
               if ((lspLocalLabelInfoBuilder != null) && (dstDeviceUpdated || srcDeviceUpdated)) {
                   lspLabelInfoList.set(i, lspLocalLabelInfoBuilder.build());
               }
           }
       }

       // If it is not found in store then add it to store
       if (!dstDeviceUpdated || !srcDeviceUpdated) {
           // If tunnel info itself not available then create new one, otherwise add node to list.
           if (lspLabelInfoList == null) {
              lspLabelInfoList = new LinkedList<>();
           }

           if (!dstDeviceUpdated) {
               LspLocalLabelInfo lspLocalLabelInfo = DefaultLspLocalLabelInfo.builder()
                   .deviceId(dstDeviceId)
                   .inLabelId(labelId)
                   .outLabelId(null)
                   .inPort(dstPort) // Destination device IN port will be link destination port
                   .outPort(null)
                   .build();
               lspLabelInfoList.add(lspLocalLabelInfo);
           }

           if (!srcDeviceUpdated) {
               LspLocalLabelInfo lspLocalLabelInfo = DefaultLspLocalLabelInfo.builder()
                   .deviceId(srcDeviceId)
                   .inLabelId(null)
                   .outLabelId(labelId)
                   .inPort(null)
                   .outPort(dstPort) // Source device OUT port will be link destination (remote) port
                   .build();
               lspLabelInfoList.add(lspLocalLabelInfo);
           }

           pceStore.addTunnelInfo(tunnel.tunnelId(), lspLabelInfoList);
       }
    }

    /**
     * Deallocates unused labels to device pools.
     *
     * @param tunnel tunnel between ingress to egress
     */
    public void releaseLabel(Tunnel tunnel) {

       checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
       checkNotNull(pceStore, PCE_STORE_NULL);

       Multimap<DeviceId, LabelResource> release = ArrayListMultimap.create();
       List<LspLocalLabelInfo> lspLocalLabelInfoList = pceStore.getTunnelInfo(tunnel.tunnelId());
       if ((lspLocalLabelInfoList != null) && (!lspLocalLabelInfoList.isEmpty())) {
           for (Iterator<LspLocalLabelInfo> iterator = lspLocalLabelInfoList.iterator(); iterator.hasNext();) {
               LspLocalLabelInfo lspLocalLabelInfo = iterator.next();
               DeviceId deviceId = lspLocalLabelInfo.deviceId();
               LabelResourceId inLabelId = lspLocalLabelInfo.inLabelId();
               LabelResourceId outLabelId = lspLocalLabelInfo.outLabelId();
               PortNumber inPort = lspLocalLabelInfo.inPort();
               PortNumber outPort = lspLocalLabelInfo.outPort();

               try {
                   // Push into device
                   if ((outLabelId != null) && (outPort != null)) {
                       pushLocalLabels(deviceId, outLabelId, outPort, tunnel, false,
                                       Long.valueOf(LabelType.OUT_LABEL.value), PcepLabelOp.REMOVE);
                   }

                   if ((inLabelId != null) && (inPort != null)) {
                       pushLocalLabels(deviceId, inLabelId, inPort, tunnel, false,
                                       Long.valueOf(LabelType.IN_LABEL.value), PcepLabelOp.REMOVE);
                   }
               } catch (PcepParseException e) {
                   log.error("Failed to push local label for device {}for tunnel {}.", deviceId.toString(),
                             tunnel.tunnelName().toString());
               }

               // List is stored from egress to ingress. So, using IN label id to release.
               // Only one local label is assigned to device (destination node)
               // and that is used as OUT label for source node.
               // No need to release label for last node in the list from pool because label was not allocated to
               // ingress node (source node).
               if ((iterator.hasNext()) && (inLabelId != null)) {
                   LabelResource labelRsc = new DefaultLabelResource(deviceId, inLabelId);
                   release.put(deviceId, labelRsc);
               }
           }
       }

       // Release from label pool
       if (!release.isEmpty()) {
          labelRsrcService.releaseToDevicePool(release);
       }

       pceStore.removeTunnelInfo(tunnel.tunnelId());
   }

   //Pushes local labels to the device which is specific to path [CR-case].
   private void pushLocalLabels(DeviceId deviceId, LabelResourceId labelId,
            PortNumber portNum, Tunnel tunnel,
            Boolean isBos, Long labelType, PcepLabelOp type) throws PcepParseException {

        checkNotNull(deviceId);
        checkNotNull(labelId);
        checkNotNull(portNum);
        checkNotNull(tunnel);
        checkNotNull(labelType);
        checkNotNull(type);

        PcepClient pc = getPcepClient(deviceId);
        if (pc == null) {
            log.error("PCEP client not found");
            return;
        }

        PcepLspObject lspObj;
        LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
        LinkedList<PcepLabelObject> labelObjects = new LinkedList<>();
        PcepSrpObject srpObj;
        PcepLabelDownload labelDownload = new PcepLabelDownload();
        LinkedList<PcepValueType> optionalTlv = new LinkedList<>();

        long portNo = portNum.toLong();
        portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;

        optionalTlv.add(NexthopIPv4addressTlv.of((int) portNo));

        PcepLabelObject labelObj = pc.factory().buildLabelObject()
                                   .setOFlag(labelType == OUT_LABEL_TYPE ? true : false)
                                   .setOptionalTlv(optionalTlv)
                                   .setLabel((int) labelId.labelId())
                                   .build();

        /**
         * Check whether transit node or not. For transit node, label update message should include IN and OUT labels.
         * Hence store IN label object and next when out label comes add IN and OUT label objects and encode label
         * update message and send to specified client.
         */
        if (!deviceId.equals(tunnel.path().src().deviceId()) && !deviceId.equals(tunnel.path().dst().deviceId())) {
            //Device is transit node
            if (labelType == OUT_LABEL_TYPE) {
                //Store label object having IN label value
                this.labelObj = labelObj;
                return;
            }
            //Add IN label object
            labelObjects.add(this.labelObj);
        }

        //Add OUT label object in case of transit node
        labelObjects.add(labelObj);

        srpObj = getSrpObject(pc, type, false);

        String lspId = tunnel.annotations().value(PcepAnnotationKeys.LOCAL_LSP_ID);
        String plspId = tunnel.annotations().value(PcepAnnotationKeys.PLSP_ID);
        String tunnelIdentifier = tunnel.annotations().value(PcepAnnotationKeys.PCC_TUNNEL_ID);

        LinkedList<PcepValueType> tlvs = new LinkedList<>();
        StatefulIPv4LspIdentifiersTlv lspIdTlv = new StatefulIPv4LspIdentifiersTlv(((IpTunnelEndPoint) tunnel.src())
                .ip().getIp4Address().toInt(), Short.valueOf(lspId), Short.valueOf(tunnelIdentifier),
                ((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt(),
                ((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt());
        tlvs.add(lspIdTlv);

        if (tunnel.tunnelName().value() != null) {
            SymbolicPathNameTlv pathNameTlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
            tlvs.add(pathNameTlv);
        }

        boolean delegated = (tunnel.annotations().value(DELEGATE) == null) ? false
                                                                           : Boolean.valueOf(tunnel.annotations()
                                                                                   .value(DELEGATE));
        boolean initiated = (tunnel.annotations().value(PCE_INIT) == null) ? false
                                                                           : Boolean.valueOf(tunnel.annotations()
                                                                                   .value(PCE_INIT));

        lspObj = pc.factory().buildLspObject()
                .setRFlag(false)
                .setAFlag(true)
                .setDFlag(delegated)
                .setCFlag(initiated)
                .setPlspId(Integer.valueOf(plspId))
                .setOptionalTlv(tlvs)
                .build();

        labelDownload.setLabelList(labelObjects);
        labelDownload.setLspObject(lspObj);
        labelDownload.setSrpObject(srpObj);

        labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
                            .setLabelDownload(labelDownload)
                            .build());

        PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
                                      .setPcLabelUpdateList(labelUpdateList)
                                      .build();

        pc.sendMessage(labelMsg);

        //If isBos is true, label download is done along the LSP, send PCEP update message.
        if (isBos) {
            sendPcepUpdateMsg(pc, lspObj, tunnel);
        }
    }

   //Sends PCEP update message.
   private void sendPcepUpdateMsg(PcepClient pc, PcepLspObject lspObj, Tunnel tunnel) throws PcepParseException {
       LinkedList<PcepUpdateRequest> updateRequestList = new LinkedList<>();
       LinkedList<PcepValueType> subObjects = createEroSubObj(tunnel.path());

       if (subObjects == null) {
           log.error("ERO subjects not present");
           return;
       }

       // set PathSetupTypeTlv of SRP object
       LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
       LspType lspSigType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
       llOptionalTlv.add(new PathSetupTypeTlv(lspSigType.type()));

       PcepSrpObject srpObj = pc.factory().buildSrpObject()
                              .setRFlag(false)
                              .setSrpID(SrpIdGenerators.create())
                              .setOptionalTlv(llOptionalTlv)
                              .build();

       PcepEroObject eroObj = pc.factory().buildEroObject()
                             .setSubObjects(subObjects)
                             .build();

       float  iBandwidth = 0;
       if (tunnel.annotations().value(BANDWIDTH) != null) {
           //iBandwidth = Float.floatToIntBits(Float.parseFloat(tunnel.annotations().value(BANDWIDTH)));
           iBandwidth = Float.parseFloat(tunnel.annotations().value(BANDWIDTH));
       }
       // build bandwidth object
       PcepBandwidthObject bandwidthObject = pc.factory().buildBandwidthObject()
                                             .setBandwidth(iBandwidth)
                                             .build();
       // build pcep attribute
       PcepAttribute pcepAttribute = pc.factory().buildPcepAttribute()
                                     .setBandwidthObject(bandwidthObject)
                                     .build();

       PcepMsgPath msgPath = pc.factory().buildPcepMsgPath()
                             .setEroObject(eroObj)
                             .setPcepAttribute(pcepAttribute)
                             .build();

       PcepUpdateRequest updateReq = pc.factory().buildPcepUpdateRequest()
                                    .setSrpObject(srpObj)
                                    .setMsgPath(msgPath)
                                    .setLspObject(lspObj)
                                    .build();

       updateRequestList.add(updateReq);

       //TODO: P = 1 is it P flag in PCEP obj header
       PcepUpdateMsg updateMsg = pc.factory().buildUpdateMsg()
                                 .setUpdateRequestList(updateRequestList)
                                 .build();

       pc.sendMessage(updateMsg);
   }

   private LinkedList<PcepValueType> createEroSubObj(Path path) {
       LinkedList<PcepValueType> subObjects = new LinkedList<>();
       List<Link> links = path.links();
       ConnectPoint source = null;
       ConnectPoint destination = null;
       IpAddress ipDstAddress = null;
       IpAddress ipSrcAddress = null;
       PcepValueType subObj = null;
       long portNo;

       for (Link link : links) {
           source = link.src();
           if (!(source.equals(destination))) {
               //set IPv4SubObject for ERO object
               portNo = source.port().toLong();
               portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
               ipSrcAddress = Ip4Address.valueOf((int) portNo);
               subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
               subObjects.add(subObj);
           }

           destination = link.dst();
           portNo = destination.port().toLong();
           portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
           ipDstAddress = Ip4Address.valueOf((int) portNo);
           subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
           subObjects.add(subObj);
       }
       return subObjects;
   }

   private PcepSrpObject getSrpObject(PcepClient pc, PcepLabelOp type, boolean bSFlag)
           throws PcepParseException {
       PcepSrpObject srpObj;
       boolean bRFlag = false;

       if (!type.equals(PcepLabelOp.ADD)) {
           // To cleanup labels, R bit is set
           bRFlag = true;
       }

       srpObj = pc.factory().buildSrpObject()
               .setRFlag(bRFlag)
               .setSFlag(bSFlag)
               .setSrpID(SrpIdGenerators.create())
               .build();

       return srpObj;
   }

   /**
    * Returns PCEP client.
    *
    * @return PCEP client
    */
   private PcepClient getPcepClient(DeviceId deviceId) {
       Device device = deviceService.getDevice(deviceId);

       // In future projections instead of annotations will be used to fetch LSR ID.
       String lsrId = device.annotations().value(LSRID);
       PcepClient pcc = clientController.getClient(PccId.pccId(IpAddress.valueOf(lsrId)));
       return pcc;
   }
}
