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

    public enum Result {
        SUCCESS,
        WRONG_PATH,
        TUNNEL_EXISTS,
        ID_EXISTS,
        TUNNEL_NOT_FOUND,
        TUNNEL_IN_USE,
        INTERNAL_ERROR
    }

    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) {

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

}
