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.NetworkGraph;
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 {
//    NetworkGraph graph;
    IFlowPusherService pusher;
    IFloodlightProviderService provider;
    private final static Logger log = LoggerFactory.getLogger(PlanInstallRuntime.class);

    public PlanInstallRuntime(//NetworkGraph 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;
	    }
	}
	
	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() {
	    String result = "FLOWMOD COUNT:\n";
	    for(FlowModCount count : map.values()) {
		result += count.toString() + '\n';
	    }
	    if(map.values().isEmpty()) {
		result += "No flow mods installed\n";
	    }
	    log.error(result);
	}
    }

    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.error("MEASUREMENT: convert: {} ns, push: {} ns, barrierWait: {} ns",
		    step2 - step1, step3 - step2, step4 - step3);

	}
	long end = System.nanoTime();
	log.error("MEASUREMENT: Install plan: {} ns", (end-start));
	FlowModCount.printCount();
	
	// TODO: we assume that the plan installation succeeds for now
	return true;
    }

}
