package net.onrc.onos.core.intent.runtime;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutionException;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.internal.OFMessageFuture;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.intent.FlowEntry;
import net.onrc.onos.core.util.Dpid;

import org.apache.commons.lang3.tuple.Pair;
import org.projectfloodlight.openflow.protocol.OFBarrierReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is responsible for installing plans (lists of sets of FlowEntries)
 * into local switches. In this context, a local switch is a switch for which
 * this ONOS instance is the master. It also is responsible for sending barrier
 * messages between sets.
 */

public class PlanInstallRuntime {

    IFlowPusherService pusher;
    IFloodlightProviderService provider;
    private static final Logger log = LoggerFactory.getLogger(PlanInstallRuntime.class);

    /**
     * Constructor.
     *
     * @param provider the FloodlightProviderService for list of local switches
     * @param pusher the FlowPusherService to use for FlowEntry installation
     */
    public PlanInstallRuntime(IFloodlightProviderService provider,
            IFlowPusherService pusher) {
        this.provider = provider;
        this.pusher = pusher;
    }

    /**
     * This class is a temporary class for collecting FlowMod installation
     * information. It is largely used for debugging purposes, and it should not
     * be depended on for other purposes.
     * <p>
     * TODO: This class should be wrapped into a more generic debugging
     * framework when available.
     */
    private static class FlowModCount {
        WeakReference<IOFSwitch> sw;
        long modFlows = 0;
        long delFlows = 0;
        long errors = 0;

        /**
         * Constructor.
         *
         * @param sw the switch for FlowMod statistics collection
         */
        FlowModCount(IOFSwitch sw) {
            this.sw = new WeakReference<>(sw);
        }

        /**
         * Include the FlowEntry in this switch statistics object.
         *
         * @param entry the FlowEntry to count
         */
        void addFlowEntry(FlowEntry entry) {
            switch (entry.getOperator()) {
            case ADD:
                modFlows++;
                break;
            case ERROR:
                errors++;
                break;
            case REMOVE:
                delFlows++;
                break;
            default:
                break;
            }
        }

        /**
         * Returns a string representation of this object.
         *
         * @return string representation of this object
         */
        @Override
        public String toString() {
            final IOFSwitch swTemp = sw.get();
            return "sw:" + ((swTemp == null) ? "disconnected" : swTemp.getStringId())
                    + ": modify " + modFlows + " delete " + delFlows + " error " + errors;
        }

        static Map<IOFSwitch, FlowModCount> map = new WeakHashMap<>();

        /**
         * This function is used for collecting statistics information. It
         * should be called for every FlowEntry that is pushed to the switch for
         * accurate statistics.
         * <p>
         * This class maintains a map of Switches and FlowModCount collection
         * objects, which are used for collection.
         * <p>
         * TODO: This should be refactored to use a more generic mechanism when
         * available.
         *
         * @param sw the switch that entry is being pushed to
         * @param entry the FlowEntry being pushed
         */
        static void countFlowEntry(IOFSwitch sw, FlowEntry entry) {
            FlowModCount count = map.get(sw);
            if (count == null) {
                count = new FlowModCount(sw);
                map.put(sw, count);
            }
            count.addFlowEntry(entry);
        }

        /**
         * Reset the statistics collection. It should be called when required
         * for debugging.
         */
        static void startCount() {
            map.clear();
        }

        /**
         * Print out the statistics information when required for debugging.
         */
        static void printCount() {
            StringBuilder result = new StringBuilder();

            result.append("FLOWMOD COUNT:\n");
            for (FlowModCount count : map.values()) {
                result.append(count.toString() + '\n');
            }
            if (map.values().isEmpty()) {
                result.append("No flow mods installed\n");
            }
            log.debug(result.toString());
        }
    }

    /**
     * This function should be called to install the FlowEntries in the plan.
     * <p>
     * Each set of FlowEntries can be installed together, but all entries should
     * be installed proceeded to the next set.
     * <p>
     * TODO: This method lack coordination between the other ONOS instances
     * before proceeded with the next set of entries
     *
     * @param plan list of set of FlowEntries for installation on local switches
     * @return true (we assume installation is successful)
     */
    public boolean installPlan(List<Set<FlowEntry>> plan) {
        long start = System.nanoTime();
        Map<Long, IOFSwitch> switches = provider.getSwitches();

        log.debug("IOFSwitches: {}", switches);
        FlowModCount.startCount();
        for (Set<FlowEntry> phase : plan) {
            Set<Pair<Dpid, FlowEntry>> entries = new HashSet<>();
            Set<IOFSwitch> modifiedSwitches = new HashSet<>();

            long step1 = System.nanoTime();
            // convert flow entries and create pairs
            for (FlowEntry entry : phase) {
                IOFSwitch sw = switches.get(entry.getSwitch());
                if (sw == null) {
                    // no active switch, skip this flow entry
                    log.debug("Skipping flow entry: {}", entry);
                    continue;
                }
                entries.add(Pair.of(new Dpid(entry.getSwitch()), entry));
                modifiedSwitches.add(sw);
                FlowModCount.countFlowEntry(sw, entry);
            }
            long step2 = System.nanoTime();

            // push flow entries to switches
            log.debug("Pushing flow entries: {}", entries);
            pusher.pushFlowEntries(entries);
            long step3 = System.nanoTime();

            // insert a barrier after each phase on each modifiedSwitch
            // wait for confirmation messages before proceeding
            List<Pair<IOFSwitch, OFMessageFuture<OFBarrierReply>>> barriers = new ArrayList<>();
            for (IOFSwitch sw : modifiedSwitches) {
                barriers.add(Pair.of(sw, pusher.barrierAsync(new Dpid(sw.getId()))));
            }
            for (Pair<IOFSwitch, OFMessageFuture<OFBarrierReply>> pair : barriers) {
                IOFSwitch sw = pair.getLeft();
                OFMessageFuture<OFBarrierReply> future = pair.getRight();
                try {
                    future.get();
                } catch (InterruptedException | ExecutionException e) {
                    log.error("Barrier message not received for sw: {}", sw);
                }
            }
            long step4 = System.nanoTime();
            log.debug("MEASUREMENT: convert: {} ns, push: {} ns, barrierWait: {} ns",
                    step2 - step1, step3 - step2, step4 - step3);

        }
        long end = System.nanoTime();
        log.debug("MEASUREMENT: Install plan: {} ns", (end - start));
        FlowModCount.printCount();

        // TODO: we assume that the plan installation succeeds for now
        return true;
    }
}
