/*
 * 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.provider.nil;
import java.util.Arrays;
import static com.google.common.base.Preconditions.checkArgument;

/**
 * Fat-tree topology simulator.
 */
public class FatTreeTopologySimulator extends TopologySimulator {

    private static final int DEFAULT_NUMBER_OF_PORTS_PER_SWITCH = 4;
    protected int kPorts;
    protected int numberOfPods;
    protected int numberOfAggLayerSwitches;
    protected int numberOfCoreLayerSwitches;
    protected int numberOfEdgeLayerSwitches;

    @Override
    protected void processTopoShape(String shape) {
        super.processTopoShape(shape);

        // If switch ports are not provided use a default value
        int k = (topoShape.length == 1) ?
                DEFAULT_NUMBER_OF_PORTS_PER_SWITCH :
                Integer.parseInt(topoShape[1]);

        // A fat-tree is parametrized by the total number of ports per switch.
        // check top of page 4 of http://web.eecs.umich.edu/~mosharaf/Readings/Fat-Tree.pdf
        kPorts = k;
        numberOfPods = k;
        numberOfCoreLayerSwitches = (k / 2) * (k / 2);
        numberOfAggLayerSwitches = k * k / 2;
        numberOfEdgeLayerSwitches = k * k / 2;

        // need to also change hostCount variable of TopologySimulator
        hostCount = kPorts / 2;
    }


    @Override
    public void setUpTopology() {

        checkArgument(kPorts > 1, "Fat Tree switches must " +
                       "have at **least** 2 ports each!");

        // this is the total number of **Switches**
        // in a fat-tree topology
        deviceCount = numberOfAggLayerSwitches +
                      numberOfCoreLayerSwitches +
                      numberOfEdgeLayerSwitches;

        log.info("Booting a {} with {}-ports, {} switches in total {} pods",
                  topoShape[0], kPorts, deviceCount,  numberOfPods);


        prepareForDeviceEvents(deviceCount);
        createDevices();
        waitForDeviceEvents();

        createLinks();
        createHosts();
    }

    @Override
    protected void createLinks() {

        // For each switch keep a count of used ports
        int[] portList = new int[deviceCount];
        Arrays.fill(portList, 0);

        // we assume that deviceIds stores all the fat tree switches in a flat list
        int end = numberOfPods / 2;
        // from [ 0, (k/2)^2 - 1] we store (k/2)^2 core switces
        int startOfCore = 0;
        // from [ (k/2)^2, (k/2)^2 + (k^2)/2 - 1] we store (k^2)/2 aggregation switches
        int startOfAgg = (numberOfPods / 2) * (numberOfPods / 2);
        // from [ (k/2)^2 + (k^2)/2, (k/2)^2 + (k^2)/2 + (k^2)/2 -1] we store (k^2)/2 edge switches
        int startOfEdge = startOfAgg + (numberOfPods * numberOfPods) / 2;

        log.debug("startOfCore = {}, startOfAgg = {}, startOfEdge = {}",
                  startOfCore, startOfAgg, startOfEdge);

        // Create links between core and aggregation switches
        for (int x = 0; x < numberOfAggLayerSwitches; x += end) {

            // each agg.switch will handle a group of k/2 core consecutive switches
            for (int i = 0; i < end; i += 1) {
                for (int j = 0; j < end; j += 1) {
                    int coreSwitch = i * end + j;
                    int aggSwitch = startOfAgg + x + i;

                    createLink(coreSwitch,
                               aggSwitch,
                               portList[coreSwitch]++,
                               portList[aggSwitch]++);
                }
            }
        }

        // Create links between aggregation and edge switches
        for (int x = 0; x < numberOfAggLayerSwitches; x += end) {
            for (int i = 0; i <  end; i += 1) {
                for (int j = 0; j < end; j += 1) {
                    int aggSwitch = startOfAgg + x + i;
                    int edgeSwitch = startOfEdge + x + j;

                    createLink(aggSwitch,
                               edgeSwitch,
                               portList[aggSwitch]++,
                               portList[edgeSwitch]++);
                }
            }
        }
    }

    @Override
    protected void createHosts() {

        int firstEdgeSwitch = (numberOfPods / 2) * (numberOfPods / 2) +
                              (numberOfPods * numberOfPods) / 2;

        // hosts connect **only** to edge switches, each edge switch has k/2 ports free for hosts
        for (int edgeSwitch = firstEdgeSwitch; edgeSwitch < deviceCount; edgeSwitch++) {

           createHosts(deviceIds.get(edgeSwitch), kPorts / 2);
        }
    }
}
