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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.math.RandomUtils;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.Identifier;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.net.resource.Resources;

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

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Helper class which interacts with the ResourceService and provides
 * a unified API to allocate MPLS labels and VLAN Ids.
 */
public final class LabelAllocator {

    private enum Behavior {
        /**
         * Random selection.
         */
        RANDOM,
        /**
         * First fit selection.
         */
        FIRST_FIT
    }

    private static final Behavior[] BEHAVIORS = Behavior.values();

    private ResourceService resourceService;
    private LabelSelection labelSelection;

    /**
     * Creates a new label allocator. Random is the
     * default behavior.
     *
     * @param rs the resource service
     */
    public LabelAllocator(ResourceService rs) {
        this.resourceService = checkNotNull(rs);
        this.labelSelection = this.getLabelSelection(Behavior.RANDOM);
    }

    /**
     * Checks if a given string is a valid Behavior.
     *
     * @param value the string to check
     * @return true if value is a valid Behavior, false otherwise
     */
    public static boolean isInEnum(String value) {
        for (Behavior b : BEHAVIORS) {
            if (b.name().equals(value)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Changes the selection behavior.
     *
     * @param type the behavior type
     */
    public void setLabelSelection(String type) {
        if (isInEnum(type)) {
            this.labelSelection = this.getLabelSelection(type);
        }
    }

    /**
     * Retrieves the label selection behavior.
     *
     * @return the label selection behavior in use
     */
    public LabelSelection getLabelSelection() {
        return this.labelSelection;
    }

    /**
     * Returns the label selection behavior, given a behavior type.
     *
     * @param type the behavior type
     * @return the label selection behavior in use
     */
    private LabelSelection getLabelSelection(String type) {
        Behavior behavior = Behavior.valueOf(type);
        return this.getLabelSelection(behavior);
    }

    /**
     * Creates a new LabelSelection. Random is
     * the default label selection behavior.
     *
     * @param type the behavior type
     * @return the object implementing the behavior
     */
    private LabelSelection getLabelSelection(Behavior type) {
        LabelSelection selection = null;
        switch (type) {
            case FIRST_FIT:
                selection = new FirstFitSelection();
                break;
            case RANDOM:
            default:
                selection = new RandomSelection();
                break;
        }
        return selection;
    }

    /**
     * Looks for available Ids.
     *
     * @param links the links where to look for Ids
     * @param  type the encapsulation type
     * @return the mappings between key and id
     */
    private Map<LinkKey, Identifier<?>> findAvailableIDs(Set<LinkKey> links, EncapsulationType type) {

        Map<LinkKey, Identifier<?>> ids = Maps.newHashMap();
        for (LinkKey link : links) {
            Set<Identifier<?>> availableIDsatSrc = getAvailableIDs(link.src(), type);
            Set<Identifier<?>> availableIDsatDst = getAvailableIDs(link.dst(), type);
            Set<Identifier<?>> common = Sets.intersection(availableIDsatSrc, availableIDsatDst);
            if (common.isEmpty()) {
                continue;
            }
            Identifier<?> selected = labelSelection.select(common);
            if (selected == null) {
                continue;
            }
            ids.put(link, selected);
        }
        return ids;
    }

    /**
     * Looks for available Ids associated to the given connection point.
     *
     * @param cp the connection point
     * @param type the type of Id
     * @return the set of available Ids
     */
    private Set<Identifier<?>> getAvailableIDs(ConnectPoint cp, EncapsulationType type) {
        return resourceService.getAvailableResourceValues(
                Resources.discrete(cp.deviceId(), cp.port()).id(), getEncapsulationClass(type)
        );
    }

    /**
     * Method to map the encapsulation type to identifier class.
     * VLAN is the default encapsulation.
     *
     * @param type the type of encapsulation
     * @return the id class
     */
    private Class getEncapsulationClass(EncapsulationType type) {
        Class idType;
        switch (type) {
            case MPLS:
                idType = MplsLabel.class;
                break;
            case VLAN:
            default:
                idType = VlanId.class;
        }
        return idType;
    }

    /**
     * Allocates labels and associates them to links.
     *
     * @param links the links where labels will be allocated
     * @param id the intent Id
     * @param type the encapsulation type
     * @return the list of links and associated labels
     */
    public Map<LinkKey, Identifier<?>> assignLabelToLinks(Set<Link> links, IntentId id, EncapsulationType type) {

        Set<LinkKey> linkRequest = links.stream()
                .map(LinkKey::linkKey)
                .collect(Collectors.toSet());

        Map<LinkKey, Identifier<?>> availableIds = findAvailableIDs(linkRequest, type);
        if (availableIds.isEmpty()) {
            return Collections.emptyMap();
        }

        Set<Resource> resources = availableIds.entrySet().stream()
                .flatMap(x -> Stream.of(
                        Resources.discrete(
                                x.getKey().src().deviceId(),
                                x.getKey().src().port(),
                                x.getValue()
                        ).resource(),
                        Resources.discrete(
                                x.getKey().dst().deviceId(),
                                x.getKey().dst().port(),
                                x.getValue()
                        ).resource()
                ))
                .collect(Collectors.toSet());

        // FIXME resource allocated by IntentId will not be released
        // when Intent is withdrawn. Behaviour changed by ONOS-5808
        List<ResourceAllocation> allocations = resourceService.allocate(id, ImmutableList.copyOf(resources));

        if (allocations.isEmpty()) {
            return Collections.emptyMap();
        }

        return ImmutableMap.copyOf(availableIds);
    }

    /**
     * Allocates labels and associates them to source
     * and destination ports of a link.
     *
     * @param links the links on which labels will be reserved
     * @param id the intent Id
     * @param type the encapsulation type
     * @return the list of ports and associated labels
     */
    public Map<ConnectPoint, Identifier<?>> assignLabelToPorts(Set<Link> links, IntentId id, EncapsulationType type) {
        Map<LinkKey, Identifier<?>> allocation = this.assignLabelToLinks(links, id, type);
        if (allocation.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<ConnectPoint, Identifier<?>> finalAllocation = Maps.newHashMap();
        allocation.forEach((key, value) -> {
            finalAllocation.putIfAbsent(key.src(), value);
            finalAllocation.putIfAbsent(key.dst(), value);
        });
        return ImmutableMap.copyOf(finalAllocation);
    }

    /**
     * Interface for selection algorithms of the labels.
     */
    public interface LabelSelection {

        /**
         * Picks an element from values using a particular algorithm.
         *
         * @param values the values to select from
         * @return the selected identifier if values are present, null otherwise
         */
        Identifier<?> select(Set<Identifier<?>> values);

    }

    /**
     * Random label selection.
     */
    public static class RandomSelection implements LabelSelection {

        /**
         * Selects an identifier from a given set of values using
         * the random selection algorithm.
         *
         * @param values the values to select from
         * @return the selected identifier if values are present, null otherwise
         */
        @Override
        public Identifier<?> select(Set<Identifier<?>> values) {
            if (!values.isEmpty()) {
                int size = values.size();
                int index = RandomUtils.nextInt(size);
                return Iterables.get(values, index);
            }
            return null;
        }
    }

    /**
     * First fit label selection.
     */
    public static class FirstFitSelection implements LabelSelection {

        /**
         * Selects an identifier from a given set of values using
         * the first fir selection algorithm.
         *
         * @param values the values to select from
         * @return the selected identifier if values are present, null otherwise.
         */
        @Override
        public Identifier<?> select(Set<Identifier<?>> values) {
            if (!values.isEmpty()) {
                return values.iterator().next();
            }
            return null;
        }
    }

}
