/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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.layout;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.utils.Comparators;

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

/**
 * Arranges access network according to roles assigned to devices and hosts.
 */
public class AccessNetworkLayout extends LayoutAlgorithm {

    private double computeY = -350.0;
    private double serviceY = -200.0;
    private double spineY = 0.0;
    private double aggregationY = +200.0;
    private double accessY = +400.0;
    private double hostsY = +550.0;

    private double gatewayX = 900.0;
    private double rowGap = 70;
    private double computeRowGap = -120;
    private double colGap = 54;
    private double computeOffset = 800.0;
    private double gatewayGap = 200.0;
    private double gatewayOffset = -200.0;
    private double serviceGap = 800;
    private int computePerRow = 25;
    private double spinesGap = 800;
    private double aggregationGap = 400;
    private double accessGap = 400;
    private int hostsPerRow = 6;

    private int spine, aggregation, accessLeaf, serviceLeaf, gateway;

    /**
     * Creates the network layout using default layout options.
     */
    public AccessNetworkLayout() {
    }

    /**
     * Creates the network layout using the specified layout property overrides.
     *
     * @param custom overrides of the default layout properties
     */
    public AccessNetworkLayout(Map<String, Object> custom) {
        computeY = (double) custom.getOrDefault("computeY", computeY);
        serviceY = (double) custom.getOrDefault("serviceY", serviceY);
        spineY = (double) custom.getOrDefault("spineY", spineY);
        aggregationY = (double) custom.getOrDefault("aggregationY", aggregationY);
        accessY = (double) custom.getOrDefault("accessY", accessY);
        hostsY = (double) custom.getOrDefault("hostsY", hostsY);
        gatewayX = (double) custom.getOrDefault("gatewayX", gatewayX);
        rowGap = (double) custom.getOrDefault("rowGap", rowGap);
        computeRowGap = (double) custom.getOrDefault("computeRowGap", computeRowGap);
        colGap = (double) custom.getOrDefault("colGap", colGap);
        computeOffset = (double) custom.getOrDefault("computeOffset", computeOffset);
        gatewayGap = (double) custom.getOrDefault("gatewayGap", gatewayGap);
        gatewayOffset = (double) custom.getOrDefault("gatewayOffset", gatewayOffset);
        serviceGap = (double) custom.getOrDefault("serviceGap", serviceGap);
        computePerRow = (int) custom.getOrDefault("computePerRow", computePerRow);
        spinesGap = (double) custom.getOrDefault("spinesGap", spinesGap);
        aggregationGap = (double) custom.getOrDefault("aggregationGap", aggregationGap);
        accessGap = (double) custom.getOrDefault("accessGap", accessGap);
        hostsPerRow = (int) custom.getOrDefault("hostsPerRow", hostsPerRow);
    }

    @Override
    protected boolean classify(Device device) {
        if (!super.classify(device)) {
            String role;

            // Does the device have any hosts attached? If not, it's a spine
            if (hostService.getConnectedHosts(device.id()).isEmpty()) {
                // Does the device have any aggregate links to other devices?
                Multiset<DeviceId> destinations = HashMultiset.create();
                linkService.getDeviceEgressLinks(device.id()).stream()
                        .map(l -> l.dst().deviceId()).forEach(destinations::add);

                // If yes, it's the main spine; otherwise it's an aggregate spine
                role = destinations.entrySet().stream().anyMatch(e -> e.getCount() > 1) ?
                        SPINE : AGGREGATION;
            } else {
                // Does the device have any multi-home hosts attached?
                // If yes, it's a service leaf; otherwise it's an access leaf
                role = hostService.getConnectedHosts(device.id()).stream()
                        .map(Host::locations).anyMatch(s -> s.size() > 1) ?
                        LEAF : ACCESS;
            }
            deviceCategories.put(role, device.id());
        }
        return true;
    }

    @Override
    protected boolean classify(Host host) {
        if (!super.classify(host)) {
            // Is the host attached to an access leaf?
            // If so, it's an access host; otherwise it's a service host or gateway
            String role = host.locations().stream().map(ConnectPoint::deviceId)
                    .anyMatch(d -> deviceCategories.get(ACCESS)
                            .contains(deviceService.getDevice(d).id())) ?
                    ACCESS : COMPUTE;
            hostCategories.put(role, host.id());
        }
        return true;
    }

    @Override
    public void apply() {
        placeSpines();
        placeServiceLeavesAndHosts();
        placeAccessLeavesAndHosts();
    }

    private void placeSpines() {
        spine = 1;
        List<DeviceId> spines = deviceCategories.get(SPINE);
        spines.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR)
                .forEach(d -> place(d, c(spine++, spines.size(), spinesGap), spineY));
    }

    private void placeServiceLeavesAndHosts() {
        List<DeviceId> leaves = deviceCategories.get(LEAF);
        List<HostId> computes = hostCategories.get(COMPUTE);
        List<HostId> gateways = hostCategories.get(GATEWAY);
        Set<HostId> placed = Sets.newHashSet();

        serviceLeaf = 1;
        leaves.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR).forEach(id -> {
            gateway = 1;
            place(id, c(serviceLeaf++, leaves.size(), serviceGap), serviceY);

            List<HostId> gwHosts = hostService.getConnectedHosts(id).stream()
                    .map(Host::id)
                    .filter(gateways::contains)
                    .filter(hid -> !placed.contains(hid))
                    .sorted(Comparators.ELEMENT_ID_COMPARATOR)
                    .collect(Collectors.toList());

            gwHosts.forEach(hid -> {
                place(hid, serviceLeaf <= 2 ? -gatewayX : gatewayX,
                      c(gateway++, gwHosts.size(), gatewayGap, gatewayOffset));
                placed.add(hid);
            });

            List<HostId> hosts = hostService.getConnectedHosts(id).stream()
                    .map(Host::id)
                    .filter(computes::contains)
                    .filter(hid -> !placed.contains(hid))
                    .sorted(Comparators.ELEMENT_ID_COMPARATOR)
                    .collect(Collectors.toList());

            placeHostBlock(hosts, serviceLeaf <= 2 ? -computeOffset : computeOffset,
                           computeY, computePerRow, computeRowGap,
                           serviceLeaf <= 2 ? -colGap : colGap);
            placed.addAll(hosts);
        });
    }

    private void placeAccessLeavesAndHosts() {
        List<DeviceId> spines = deviceCategories.get(AGGREGATION);
        List<DeviceId> leaves = deviceCategories.get(ACCESS);
        Set<DeviceId> placed = Sets.newHashSet();

        aggregation = 1;
        accessLeaf = 1;
        if (spines.isEmpty()) {
            leaves.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR)
                    .forEach(lid -> placeAccessLeafAndHosts(lid, leaves.size(), placed));
        } else {
            spines.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR).forEach(id -> {
                place(id, c(aggregation++, spines.size(), aggregationGap), aggregationY);
                linkService.getDeviceEgressLinks(id).stream()
                        .map(l -> l.dst().deviceId())
                        .filter(leaves::contains)
                        .filter(lid -> !placed.contains(lid))
                        .sorted(Comparators.ELEMENT_ID_COMPARATOR)
                        .forEach(lid -> placeAccessLeafAndHosts(lid, leaves.size(), placed));
            });
        }
    }

    private void placeAccessLeafAndHosts(DeviceId leafId, int leafCount, Set<DeviceId> placed) {
        double x = c(accessLeaf++, leafCount, accessGap);
        place(leafId, x, accessY);
        placed.add(leafId);
        placeHostBlock(hostService.getConnectedHosts(leafId).stream()
                               .map(Host::id)
                               .sorted(Comparators.ELEMENT_ID_COMPARATOR)
                               .collect(Collectors.toList()), x, hostsY,
                       hostsPerRow, rowGap, colGap);
    }

}
