/*
 * Copyright Big Switch Networks 2012
 */

package net.floodlightcontroller.util;

import java.io.IOException;
import java.util.EnumSet;
import java.util.Set;

import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IOFSwitch;

import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFType;

/**
 * Dampens OFMessages sent to an OF switch. A message is only written to 
 * a switch if the same message (as defined by .equals()) has not been written
 * in the last n milliseconds. Timer granularity is based on TimedCache
 * @author gregor
 *
 */
public class OFMessageDamper {
    /**
     * An entry in the TimedCache. A cache entry consists of the sent message
     * as well as the switch to which the message was sent. 
     * 
     * NOTE: We currently use the full OFMessage object. To save space, we 
     * could use a cryptographic hash (e.g., SHA-1). However, this would 
     * obviously be more time-consuming.... 
     * 
     * We also store a reference to the actual IOFSwitch object and /not/
     * the switch DPID. This way we are guarnteed to not dampen messages if
     * a switch disconnects and then reconnects.
     * 
     * @author gregor
     */
    protected static class DamperEntry {
        OFMessage msg;
        IOFSwitch sw;
        public DamperEntry(OFMessage msg, IOFSwitch sw) {
            super();
            this.msg = msg;
            this.sw = sw;
        }
        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((msg == null) ? 0 : msg.hashCode());
            result = prime * result + ((sw == null) ? 0 : sw.hashCode());
            return result;
        }
        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            DamperEntry other = (DamperEntry) obj;
            if (msg == null) {
                if (other.msg != null) return false;
            } else if (!msg.equals(other.msg)) return false;
            if (sw == null) {
                if (other.sw != null) return false;
            } else if (!sw.equals(other.sw)) return false;
            return true;
        }
        
      
    }
    TimedCache<DamperEntry> cache;
    EnumSet<OFType> msgTypesToCache;
    /**
     * 
     * @param capacity the maximum number of messages that should be 
     * kept
     * @param typesToDampen The set of OFMessageTypes that should be 
     * dampened by this instance. Other types will be passed through
     * @param timeout The dampening timeout. A message will only be
     * written if the last write for the an equal message more than
     * timeout ms ago. 
     */
    public OFMessageDamper(int capacity, 
                           Set<OFType> typesToDampen,  
                           int timeout) {
        cache = new TimedCache<DamperEntry>(capacity, timeout);
        msgTypesToCache = EnumSet.copyOf(typesToDampen);
    }        
    
    /**
     * write the messag to the switch according to our dampening settings
     * @param sw
     * @param msg
     * @param cntx
     * @return true if the message was written to the switch, false if
     * the message was dampened. 
     * @throws IOException
     */
    public boolean write(IOFSwitch sw, OFMessage msg, FloodlightContext cntx)
                    throws IOException {
        return write(sw, msg, cntx, false);
    }
    
    /**
     * write the messag to the switch according to our dampening settings
     * @param sw
     * @param msg
     * @param cntx
     * @param flush true to flush the packet immidiately
     * @return true if the message was written to the switch, false if
     * the message was dampened. 
     * @throws IOException
     */
    public boolean write(IOFSwitch sw, OFMessage msg,
                        FloodlightContext cntx, boolean flush) 
            throws IOException {
        if (! msgTypesToCache.contains(msg.getType())) {
            sw.write(msg, cntx);
            if (flush) {
                sw.flush();
            }
            return true;
        }
        
        DamperEntry entry = new DamperEntry(msg, sw);
        if (cache.update(entry)) {
            // entry exists in cache. Dampening.
            return false; 
        } else {
            sw.write(msg, cntx);
            if (flush) {
                sw.flush();
            }
            return true;
        }
    }
}
