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.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<IOFSwitch, 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(new Pair<>(sw, 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(new Pair<>(sw, pusher.barrierAsync(sw)));
            }
            for (Pair<IOFSwitch, OFMessageFuture<OFBarrierReply>> pair : barriers) {
                IOFSwitch sw = pair.getFirst();
                OFMessageFuture<OFBarrierReply> future = pair.getSecond();
                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;
    }
}
