/*
 * Copyright 2015 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.segmentrouting;

import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Tunnel Handler.
 */
public class TunnelHandler {
    protected final Logger log = getLogger(getClass());

    private final DeviceConfiguration config;
    private final EventuallyConsistentMap<String, Tunnel> tunnelStore;
    private Map<DeviceId, DefaultGroupHandler> groupHandlerMap;
    private LinkService linkService;

    /**
     * Result of tunnel creation or removal.
     */
    public enum Result {
        /**
         * Success.
         */
        SUCCESS,

        /**
         * More than one router needs to specified to created a tunnel.
         */
        WRONG_PATH,

        /**
         * The same tunnel exists already.
         */
        TUNNEL_EXISTS,

        /**
         * The same tunnel ID exists already.
         */
        ID_EXISTS,

        /**
         * Tunnel not found.
         */
        TUNNEL_NOT_FOUND,

        /**
         * Cannot remove the tunnel used by a policy.
         */
        TUNNEL_IN_USE,

        /**
         * Failed to create/remove groups for the tunnel.
         */
        INTERNAL_ERROR
    }

    /**
     * Constructs tunnel handler.
     *
     * @param linkService link service
     * @param deviceConfiguration device configuration
     * @param groupHandlerMap group handler map
     * @param tunnelStore tunnel store
     */
    public TunnelHandler(LinkService linkService,
                         DeviceConfiguration deviceConfiguration,
                         Map<DeviceId, DefaultGroupHandler> groupHandlerMap,
                         EventuallyConsistentMap<String, Tunnel> tunnelStore) {
        this.linkService = linkService;
        this.config = deviceConfiguration;
        this.groupHandlerMap = groupHandlerMap;
        this.tunnelStore = tunnelStore;
    }

    /**
     * Creates a tunnel.
     *
     * @param tunnel tunnel reference to create a tunnel
     * @return WRONG_PATH if the tunnel path is wrong, ID_EXISTS if the tunnel ID
     * exists already, TUNNEL_EXISTS if the same tunnel exists, INTERNAL_ERROR
     * if the tunnel creation failed internally, SUCCESS if the tunnel is created
     * successfully
     */
    public Result createTunnel(Tunnel tunnel) {

        if (tunnel.labelIds().isEmpty() || tunnel.labelIds().size() < 3) {
            log.error("More than one router needs to specified to created a tunnel");
            return Result.WRONG_PATH;
        }

        if (tunnelStore.containsKey(tunnel.id())) {
            log.warn("The same tunnel ID exists already");
            return Result.ID_EXISTS;
        }

        if (tunnelStore.containsValue(tunnel)) {
            log.warn("The same tunnel exists already");
            return Result.TUNNEL_EXISTS;
        }

        int groupId = createGroupsForTunnel(tunnel);
        if (groupId < 0) {
            log.error("Failed to create groups for the tunnel");
            return Result.INTERNAL_ERROR;
        }

        tunnel.setGroupId(groupId);
        tunnelStore.put(tunnel.id(), tunnel);

        return Result.SUCCESS;
    }

    /**
     * Removes the tunnel with the tunnel ID given.
     *
     * @param tunnelInfo tunnel information to delete tunnels
     * @return TUNNEL_NOT_FOUND if the tunnel to remove does not exists,
     * INTERNAL_ERROR if the tunnel creation failed internally, SUCCESS
     * if the tunnel is created successfully.
     */
    public Result removeTunnel(Tunnel tunnelInfo) {

        Tunnel tunnel = tunnelStore.get(tunnelInfo.id());
        if (tunnel != null) {
            DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
            if (tunnel.isAllowedToRemoveGroup()) {
                if (groupHandlerMap.get(deviceId).removeGroup(tunnel.groupId())) {
                    tunnelStore.remove(tunnel.id());
                } else {
                    log.error("Failed to remove the tunnel {}", tunnelInfo.id());
                    return Result.INTERNAL_ERROR;
                }
            } else {
                log.debug("The group is not removed because it is being used.");
                tunnelStore.remove(tunnel.id());
            }
        } else {
            log.error("No tunnel found for tunnel ID {}", tunnelInfo.id());
            return Result.TUNNEL_NOT_FOUND;
        }

        return Result.SUCCESS;
    }

    /**
     * Returns the tunnel with the tunnel ID given.
     *
     * @param tid Tunnel ID
     * @return Tunnel reference
     */
    public Tunnel getTunnel(String tid) {
        return tunnelStore.get(tid);
    }

    /**
     * Returns all tunnels.
     *
     * @return list of Tunnels
     */
    public List<Tunnel> getTunnels() {
        List<Tunnel> tunnels = new ArrayList<>();
        tunnelStore.values().forEach(tunnel -> tunnels.add(
                new DefaultTunnel((DefaultTunnel) tunnel)));

        return tunnels;
    }

    private int createGroupsForTunnel(Tunnel tunnel) {

        Set<Integer> portNumbers;
        final int groupError = -1;

        DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
        if (deviceId == null) {
            log.warn("No device found for SID {}", tunnel.labelIds().get(0));
            return groupError;
        } else if (groupHandlerMap.get(deviceId) == null) {
            log.warn("group handler not found for {}", deviceId);
            return groupError;
        }
        Set<DeviceId> deviceIds = new HashSet<>();
        int sid = tunnel.labelIds().get(1);
        if (config.isAdjacencySid(deviceId, sid)) {
            portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
            for (Link link: linkService.getDeviceEgressLinks(deviceId)) {
                for (Integer port: portNumbers) {
                    if (link.src().port().toLong() == port) {
                        deviceIds.add(link.dst().deviceId());
                    }
                }
            }
        } else {
            deviceIds.add(config.getDeviceId(sid));
        }

        NeighborSet ns = new NeighborSet(deviceIds, tunnel.labelIds().get(2));

        // If the tunnel reuses any existing groups, then tunnel handler
        // should not remove the group.
        if (groupHandlerMap.get(deviceId).hasNextObjectiveId(ns)) {
            tunnel.allowToRemoveGroup(false);
        } else {
            tunnel.allowToRemoveGroup(true);
        }

        return groupHandlerMap.get(deviceId).getNextObjectiveId(ns, null);
    }

}
