package net.onrc.onos.ofcontroller.flowprogrammer;

import java.io.IOException;
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 java.util.concurrent.Future;

import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFPort;
import org.openflow.protocol.OFStatisticsRequest;
import org.openflow.protocol.statistics.OFFlowStatisticsReply;
import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
import org.openflow.protocol.statistics.OFStatistics;
import org.openflow.protocol.statistics.OFStatisticsType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.floodlightcontroller.core.IOFSwitch;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.util.Dpid;
import net.onrc.onos.ofcontroller.util.FlowEntryId;

public class FlowSynchronizer implements IFlowSyncService {

    private static Logger log = LoggerFactory.getLogger(FlowSynchronizer.class);

    private GraphDBOperation dbHandler;
    protected IFlowPusherService pusher;
    private Map<IOFSwitch, Thread> switchThreads; 

    public FlowSynchronizer() {
	dbHandler = new GraphDBOperation("");
	switchThreads = new HashMap<IOFSwitch, Thread>();
    }

    @Override
    public void synchronize(IOFSwitch sw) {
	Synchronizer sync = new Synchronizer(sw);
	Thread t = new Thread(sync);
	switchThreads.put(sw, t);
	t.start();
    }
    
    @Override
    public void interrupt(IOFSwitch sw) {
	Thread t = switchThreads.remove(sw);
	if(t != null) {
	    t.interrupt();
	}	
    }

    public void init(IFlowPusherService pusherService) {
	pusher = pusherService;
    }

    protected class Synchronizer implements Runnable {
	IOFSwitch sw;
	ISwitchObject swObj;

	public Synchronizer(IOFSwitch sw) {
	    this.sw = sw;
	    Dpid dpid = new Dpid(sw.getId());
	    this.swObj = dbHandler.searchSwitch(dpid.toString());
	}

	@Override
	public void run() {
	    // TODO: stop adding other flow entries while synchronizing
	    //pusher.suspend(sw);
	    Set<FlowEntryWrapper> graphEntries = getFlowEntriesFromGraph();
	    Set<FlowEntryWrapper> switchEntries = getFlowEntriesFromSwitch();
	    compare(graphEntries, switchEntries);
	    //pusher.resume(sw);
	}

	private void compare(Set<FlowEntryWrapper> graphEntries, Set<FlowEntryWrapper> switchEntries) {
	    int added = 0, removed = 0, skipped = 0;
	    for(FlowEntryWrapper entry : switchEntries) {
		if(graphEntries.contains(entry)) {
		    graphEntries.remove(entry);
		    skipped++;
		}
		else {
		    // remove flow entry from the switch
		    entry.removeFromSwitch(sw);
		    removed++;
		}
	    }
	    for(FlowEntryWrapper entry : graphEntries) {
		// add flow entry to switch
		entry.addToSwitch(sw);
		added++;
	    }	  
	    log.debug("Flow entries added "+ added + ", " +
		      "Flow entries removed "+ removed + ", " +
		      "Flow entries skipped " + skipped);
	}

	private Set<FlowEntryWrapper> getFlowEntriesFromGraph() {
	    Set<FlowEntryWrapper> entries = new HashSet<FlowEntryWrapper>();
	    for(IFlowEntry entry : swObj.getFlowEntries()) {
		FlowEntryWrapper fe = new FlowEntryWrapper(entry);
		entries.add(fe);
	    }
	    return entries;	    
	}

	private Set<FlowEntryWrapper> getFlowEntriesFromSwitch() {

	    int lengthU = 0;
	    OFMatch match = new OFMatch();
	    match.setWildcards(OFMatch.OFPFW_ALL);

	    OFFlowStatisticsRequest stat = new OFFlowStatisticsRequest();
	    stat.setOutPort((short) 0xffff); //TODO: OFPort.OFPP_NONE
	    stat.setTableId((byte) 0xff); // TODO: fix this with enum (ALL TABLES)
	    stat.setMatch(match);
	    List<OFStatistics> stats = new ArrayList<OFStatistics>();
	    stats.add(stat);
	    lengthU += stat.getLength();

	    OFStatisticsRequest req = new OFStatisticsRequest();
	    req.setStatisticType(OFStatisticsType.FLOW);
	    req.setStatistics(stats);
	    lengthU += req.getLengthU();
	    req.setLengthU(lengthU);

	    List<OFStatistics> entries = null;
	    try {
		Future<List<OFStatistics>> dfuture = sw.getStatistics(req);
		entries = dfuture.get();
	    } catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    } catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    } catch (ExecutionException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }

	    Set<FlowEntryWrapper> results = new HashSet<FlowEntryWrapper>();
	    for(OFStatistics result : entries){
		OFFlowStatisticsReply entry = (OFFlowStatisticsReply) result;
		FlowEntryWrapper fe = new FlowEntryWrapper(entry);
		results.add(fe);
	    }
	    return results;
	}

    }

    class FlowEntryWrapper {
	FlowEntryId id;
	IFlowEntry iflowEntry;
	OFFlowStatisticsReply statisticsReply;

	public FlowEntryWrapper(IFlowEntry entry) {
	    iflowEntry = entry;
	    id = new FlowEntryId(entry.getFlowEntryId());
	}

	public FlowEntryWrapper(OFFlowStatisticsReply entry) {
	    statisticsReply = entry;
	    id = new FlowEntryId(entry.getCookie());
	}

	public void addToSwitch(IOFSwitch sw) {
	    if(iflowEntry != null) {
		pusher.add(sw, iflowEntry.getFlow(), iflowEntry);
	    }
	    else if(statisticsReply != null) {
		log.error("Adding existing flow entry {} to sw {}", 
			  statisticsReply.getCookie(), sw.getId());
	    }
	}
	
	public void removeFromSwitch(IOFSwitch sw){
	    if(iflowEntry != null) {
		log.error("Removing non-existent flow entry {} from sw {}", 
			  iflowEntry.getFlowEntryId(), sw.getId());

	    }
	    else if(statisticsReply != null) {
		// Convert Statistics Reply to Flow Mod, then write it
		OFFlowMod fm = new OFFlowMod();
		fm.setCookie(statisticsReply.getCookie());
		fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);
		fm.setLengthU(OFFlowMod.MINIMUM_LENGTH);
		fm.setMatch(statisticsReply.getMatch());
		fm.setPriority(statisticsReply.getPriority());
		fm.setOutPort(OFPort.OFPP_NONE);
		pusher.add(sw, fm);
	    }
	}

	/**
	 * Return the hash code of the Flow Entry ID
	 */
	@Override
	public int hashCode() {
	    return id.hashCode();
	}

	/**
	 * Returns true of the object is another Flow Entry ID with 
	 * the same value; otherwise, returns false.
	 * 
	 * @param Object to compare
	 */
	@Override
	public boolean equals(Object obj){
	    if(obj.getClass() == this.getClass()) {
		FlowEntryWrapper entry = (FlowEntryWrapper) obj;
		// TODO: we need to actually compare the match + actions
		return this.id.equals(entry.id);
	    }
	    return false;
	}

	@Override
	public String toString() {
	    return id.toString();
	}
    }


}


