/*
 * 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.pce.pceservice;

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.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.Tunnel;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.pce.pcestore.api.LspLocalLabelInfo;
import org.onosproject.pce.pcestore.PceccTunnelInfo;
import org.onosproject.pce.pcestore.DefaultLspLocalLabelInfo;
import org.onosproject.net.Link;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * 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);

    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 PceStore pceStore;

    /**
     * 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 pceStore pce label store
     */
    public void initialize(LabelResourceService labelRsrcService, PceStore pceStore) {
        this.labelRsrcService = labelRsrcService;
        this.pceStore = pceStore;
    }

    /**
     * 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.size() > 0)) {
            // Sequence through reverse order to push local labels into devices
            // Generation of labels from egress to ingress
            for (ListIterator iterator = linkList.listIterator(linkList.size()); iterator.hasPrevious();) {
                Link link = (Link) iterator.previous();
                DeviceId dstDeviceId = link.dst().deviceId();
                DeviceId srcDeviceId = link.src().deviceId();
                labelRscList = labelRsrcService.applyFromDevicePool(dstDeviceId, applyNum);
                if ((labelRscList != null) && (labelRscList.size() > 0)) {
                    // 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;
                    }

                    // Push into destination device
                    //TODO: uncomment below lines once installLocalLabelRule() method is ready
                    // Destination device IN port is link.dst().port()
                    //installLocalLabelRule(dstDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
                    //                      LabelType.IN, Objective.Operation.ADD);

                    // Push into source device
                    //TODO: uncomment below lines once installLocalLabelRule() method is ready
                    // Source device OUT port will be link.dst().port(). Means its remote port used to send packet.
                    //installLocalLabelRule(srcDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
                    //                      LabelType.OUT, Objective.Operation.ADD);

                    // Add or update pcecc tunnel info in pce store.
                    updatePceccTunnelInfoInStore(srcDeviceId, dstDeviceId, labelId, dstPort,
                                                 tunnel, isLastLabelToPush);
                } 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
     * @param isLastLabelToPush indicates this is the last label to push in Basic PCECC case
     */
    public void updatePceccTunnelInfoInStore(DeviceId srcDeviceId, DeviceId dstDeviceId, LabelResourceId labelId,
                                                PortNumber dstPort, Tunnel tunnel, boolean isLastLabelToPush) {
       // 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;

       PceccTunnelInfo pceccTunnelInfo = pceStore.getTunnelInfo(tunnel.tunnelId());
       List<LspLocalLabelInfo> lspLabelInfoList;
       if (pceccTunnelInfo != null) {
           lspLabelInfoList = pceccTunnelInfo.lspLocalLabelInfoList();
           if ((lspLabelInfoList != null) && (lspLabelInfoList.size() > 0)) {
               for (int i = 0; i < lspLabelInfoList.size(); ++i) {
                   LspLocalLabelInfo lspLocalLabelInfo =
                           (DefaultLspLocalLabelInfo) 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 (pceccTunnelInfo == null) {
              pceccTunnelInfo = new PceccTunnelInfo();
              lspLabelInfoList = new LinkedList<>();
           } else {
              lspLabelInfoList = pceccTunnelInfo.lspLocalLabelInfoList();
              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);
           }

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

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

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

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

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

                   // Push into device
                   if ((inLabelId != null) && (inPort != null)) {
                       //TODO: uncomment below lines once installLocalLabelRule() method is ready
                       //installLocalLabelRule(deviceId, inLabelId, inPort, tunnelId, isLastLabelToPush,
                       //                      LabelType.IN, Objective.Operation.REMOVE);
                   }

                   if ((outLabelId != null) && (outPort != null)) {
                       //TODO: uncomment below lines once installLocalLabelRule() method is ready
                       //installLocalLabelRule(deviceId, outLabelId, outPort, tunnelId, isLastLabelToPush,
                       //                      LabelType.OUT, Objective.Operation.REMOVE);
                   }

                   // 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);
           }

           // Remove tunnel info only if tunnel consumer id is not saved.
           // If tunnel consumer id is saved, this tunnel info will be removed during releasing bandwidth.
           if (pceccTunnelInfo.tunnelConsumerId() == null) {
               pceStore.removeTunnelInfo(tunnel.tunnelId());
           }
       } else {
           log.error("Unable to find PCECC tunnel info in store for a tunnel {}.", tunnel.toString());
       }
   }
}
