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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.topology.Topology;
import net.onrc.onos.core.util.Pair;

import org.openflow.protocol.OFBarrierReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Brian O'Connor <bocon@onlab.us>
 */

public class PlanInstallRuntime {
    //    Topology graph;
    IFlowPusherService pusher;
    IFloodlightProviderService provider;
    private static final Logger log = LoggerFactory.getLogger(PlanInstallRuntime.class);

    public PlanInstallRuntime(//Topology graph,
                              IFloodlightProviderService provider,
                              IFlowPusherService pusher) {
//      this.graph = graph;
        this.provider = provider;
        this.pusher = pusher;
    }

    private static class FlowModCount {
        IOFSwitch sw;
        long modFlows = 0;
        long delFlows = 0;
        long errors = 0;

        FlowModCount(IOFSwitch sw) {
            this.sw = sw;
        }

        void addFlowEntry(FlowEntry entry) {
            switch (entry.getOperator()) {
                case ADD:
                    modFlows++;
                    break;
                case ERROR:
                    errors++;
                    break;
                case REMOVE:
                    delFlows++;
                    break;
                default:
                    break;
            }
        }

        @Override
        public String toString() {
            return "sw:" + sw.getStringId() + ": modify " + modFlows + " delete " + delFlows + " error " + errors;
        }

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

        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);
        }

        static void startCount() {
            map.clear();
        }

        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());
        }
    }

    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, net.onrc.onos.core.util.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.getFlowEntry()));
                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();

            // TODO: insert a barrier after each phase on each modifiedSwitch
            // TODO: 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.first;
                OFMessageFuture<OFBarrierReply> future = pair.second;
                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;
    }
}
