/*
 * Copyright 2016-present 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.pcep.controller.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.controller.LspType;
import org.onosproject.pcep.controller.PccId;
import org.onosproject.pcep.controller.PcepAnnotationKeys;
import org.onosproject.pcep.controller.PcepClient;
import org.onosproject.pcep.controller.PcepClientController;
import org.onosproject.pcep.controller.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.controller.PcepAnnotationKeys.BANDWIDTH;
import static org.onosproject.pcep.controller.PcepAnnotationKeys.LSP_SIG_TYPE;
import static org.onosproject.pcep.controller.PcepAnnotationKeys.PCE_INIT;
import static org.onosproject.pcep.controller.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;
   }
}
