package net.floodlightcontroller.debugcounter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Sets;

import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.debugcounter.web.DebugCounterRoutable;
import net.floodlightcontroller.restserver.IRestApiService;

/**
 * This class implements a central store for all counters used for debugging the
 * system. For counters based on traffic-type, see ICounterStoreService.
 *
 * @author saurav
 */
public class DebugCounter implements IFloodlightModule, IDebugCounterService {
    protected static Logger log = LoggerFactory.getLogger(DebugCounter.class);

    /**
     * registered counters need a counter id
     */
    protected AtomicInteger counterIdCounter = new AtomicInteger();

    /**
     * The counter value
     */
    protected class MutableLong {
        long value = 0;
        public void increment() { value += 1; }
        public void increment(long incr) { value += incr; }
        public long get() { return value; }
        public void set(long val) { value = val; }
      }

    /**
     * protected class to store counter information
     */
    public static class CounterInfo {
        String moduleCounterHierarchy;
        String counterDesc;
        CounterType ctype;
        String moduleName;
        String counterHierarchy;
        int counterId;
        boolean enabled;
        String[] metaData;

        public CounterInfo(int counterId, boolean enabled,
                           String moduleName, String counterHierarchy,
                           String desc, CounterType ctype, String... metaData) {
            this.moduleCounterHierarchy = moduleName + "/" + counterHierarchy;
            this.moduleName = moduleName;
            this.counterHierarchy = counterHierarchy;
            this.counterDesc = desc;
            this.ctype = ctype;
            this.counterId = counterId;
            this.enabled = enabled;
            this.metaData = metaData;
        }

        public String getModuleCounterHierarchy() { return moduleCounterHierarchy; }
        public String getCounterDesc() { return counterDesc; }
        public CounterType getCtype() { return ctype; }
        public String getModuleName() { return moduleName; }
        public String getCounterHierarchy() { return counterHierarchy; }
        public int getCounterId() { return counterId; }
        public boolean isEnabled() { return enabled; }
        public String[] getMetaData() { return metaData; }
    }

    //******************
    //   Global stores
    //******************

    /**
     * Counter info for a debug counter
     */
    public class DebugCounterInfo {
        CounterInfo cinfo;
        AtomicLong cvalue;

        public DebugCounterInfo(CounterInfo cinfo) {
            this.cinfo = cinfo;
            this.cvalue = new AtomicLong();
        }
        public CounterInfo getCounterInfo() {
            return cinfo;
        }
        public Long getCounterValue() {
            return cvalue.get();
        }
    }

    /**
     * Global debug-counter storage across all threads. These are
     * updated from the local per thread counters by the flush counters method.
     */
    protected static DebugCounterInfo[] allCounters =
                            new DebugCounterInfo[MAX_COUNTERS];


    /**
     * per module counters, indexed by the module name and storing three levels
     * of Counter information in the form of CounterIndexStore
     */
    protected ConcurrentHashMap<String, ConcurrentHashMap<String, CounterIndexStore>>
        moduleCounters = new ConcurrentHashMap<String,
                                                ConcurrentHashMap<String,
                                                                   CounterIndexStore>>();

    protected class CounterIndexStore {
        int index;
        Map<String, CounterIndexStore> nextLevel;

        public CounterIndexStore(int index, Map<String,CounterIndexStore> cis) {
            this.index = index;
            this.nextLevel = cis;
        }
    }

    /**
     * fast global cache for counter ids that are currently active
     */
    protected Set<Integer> currentCounters = Collections.newSetFromMap(
                                         new ConcurrentHashMap<Integer,Boolean>());

    //******************
    // Thread local stores
    //******************

    /**
     * Thread local storage of counter info
     */
    protected class LocalCounterInfo {
        boolean enabled;
        MutableLong cvalue;

        public LocalCounterInfo(boolean enabled) {
            this.enabled = enabled;
            this.cvalue = new MutableLong();
        }
    }

    /**
     * Thread local debug counters used for maintaining counters local to a thread.
     */
    protected final ThreadLocal<LocalCounterInfo[]> threadlocalCounters =
            new ThreadLocal<LocalCounterInfo[]>() {
        @Override
        protected LocalCounterInfo[] initialValue() {
            return new LocalCounterInfo[MAX_COUNTERS];
        }
    };

    /**
     * Thread local cache for counter ids that are currently active.
     */
    protected final ThreadLocal<Set<Integer>> threadlocalCurrentCounters =
            new ThreadLocal<Set<Integer>>() {
        @Override
        protected Set<Integer> initialValue() {
            return new HashSet<Integer>();
        }
    };

    //*******************************
    //   IDebugCounter
    //*******************************

    protected class CounterImpl implements IDebugCounter {
        private final int counterId;

        public CounterImpl(int counterId) {
            this.counterId = counterId;
        }

        @Override
        public void updateCounterWithFlush() {
            if (!validCounterId()) return;
            updateCounter(counterId, 1, true);
        }

        @Override
        public void updateCounterNoFlush() {
            if (!validCounterId()) return;
            updateCounter(counterId, 1, false);
        }

        @Override
        public void updateCounterWithFlush(int incr) {
            if (!validCounterId()) return;
            updateCounter(counterId, incr, true);
        }

        @Override
        public void updateCounterNoFlush(int incr) {
            if (!validCounterId()) return;
            updateCounter(counterId, incr, false);
        }

        @Override
        public long getCounterValue() {
            if (!validCounterId()) return -1;
            return allCounters[counterId].cvalue.get();
        }

        private boolean validCounterId() {
            if (counterId < 0 || counterId >= MAX_COUNTERS) {
                log.error("Invalid counterId invoked");
                return false;
            }
            return true;
        }

    }

   //*******************************
   //   IDebugCounterService
   //*******************************

   @Override
   public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
                           String counterDescription, CounterType counterType,
                           String... metaData)
               throws MaxCountersRegistered, MaxHierarchyRegistered,
                      MissingHierarchicalLevel {
       // check if counter already exists
       if (!moduleCounters.containsKey(moduleName)) {
           moduleCounters.putIfAbsent(moduleName,
                new ConcurrentHashMap<String, CounterIndexStore>());
       }
       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
       if (rci.allLevelsFound) {
           // counter exists
           log.info("Counter exists for {}/{} -- resetting counters", moduleName,
                    counterHierarchy);
           resetCounterHierarchy(moduleName, counterHierarchy);
           return new CounterImpl(rci.ctrIds[rci.foundUptoLevel-1]);
       }
       // check for validity of counter
       if (rci.levels.length > MAX_HIERARCHY) {
           String err = "Registry of counterHierarchy " + counterHierarchy +
                   " exceeds max hierachy " + MAX_HIERARCHY + ".. aborting";
           throw new MaxHierarchyRegistered(err);
       }
       if (rci.foundUptoLevel < rci.levels.length-1) {
           String needToRegister = "";
           for (int i=0; i<=rci.foundUptoLevel; i++) {
               needToRegister += rci.levels[i];
           }
           String err = "Attempting to register hierarchical counterHierarchy " +
                   counterHierarchy + " but parts of hierarchy missing. " +
                   "Please register " +  needToRegister + " first";
           throw new MissingHierarchicalLevel(err);
       }

       // get a new counter id
       int counterId = counterIdCounter.getAndIncrement();
       if (counterId >= MAX_COUNTERS) {
           throw new MaxCountersRegistered("max counters reached");
       }
       // create storage for counter
       boolean enabled = (counterType == CounterType.ALWAYS_COUNT) ? true : false;
       CounterInfo ci = new CounterInfo(counterId, enabled, moduleName,
                                        counterHierarchy, counterDescription,
                                        counterType, metaData);
       allCounters[counterId] = new DebugCounterInfo(ci);

       // account for the new counter in the module counter hierarchy
       addToModuleCounterHierarchy(moduleName, counterId, rci);

       // finally add to active counters
       if (enabled) {
           currentCounters.add(counterId);
       }
       return new CounterImpl(counterId);
   }

   private void updateCounter(int counterId, int incr, boolean flushNow) {
       if (counterId < 0 || counterId >= MAX_COUNTERS) return;

       LocalCounterInfo[] thiscounters =  this.threadlocalCounters.get();
       if (thiscounters[counterId] == null) {
           // seeing this counter for the first time in this thread - create local
           // store by consulting global store
           DebugCounterInfo dc = allCounters[counterId];
           if (dc != null) {
               thiscounters[counterId] = new LocalCounterInfo(dc.cinfo.enabled);
               if (dc.cinfo.enabled) {
                   Set<Integer> thisset = this.threadlocalCurrentCounters.get();
                   thisset.add(counterId);
               }
           } else {
               log.error("updateCounter seen locally for counter {} but no global"
                          + "storage exists for it yet .. not updating", counterId);
               return;
           }
       }

       // update local store if enabled locally for updating
       LocalCounterInfo lc = thiscounters[counterId];
       if (lc.enabled) {
           lc.cvalue.increment(incr);
           if (flushNow) {
               DebugCounterInfo dc = allCounters[counterId];
               if (dc.cinfo.enabled) {
                   // globally enabled - flush now
                   dc.cvalue.addAndGet(lc.cvalue.get());
                   lc.cvalue.set(0);
               } else {
                   // global counter is disabled - don't flush, disable locally
                   lc.enabled = false;
                   Set<Integer> thisset = this.threadlocalCurrentCounters.get();
                   thisset.remove(counterId);
               }
           }
       }
   }

   @Override
   public void flushCounters() {
       LocalCounterInfo[] thiscounters =  this.threadlocalCounters.get();
       Set<Integer> thisset = this.threadlocalCurrentCounters.get();
       ArrayList<Integer> temp = new ArrayList<Integer>();

       for (int counterId : thisset) {
           LocalCounterInfo lc = thiscounters[counterId];
           if (lc.cvalue.get() > 0) {
               DebugCounterInfo dc = allCounters[counterId];
               if (dc.cinfo.enabled) {
                   // globally enabled - flush now
                   dc.cvalue.addAndGet(lc.cvalue.get());
                   lc.cvalue.set(0);
               } else {
                   // global counter is disabled - don't flush, disable locally
                   lc.enabled = false;
                   temp.add(counterId);
               }
           }
       }
       for (int cId : temp) {
           thisset.remove(cId);
       }

       // At this point it is possible that the thread-local set does not
       // include a counter that has been enabled and is present in the global set.
       // We need to sync thread-local currently enabled set of counterIds with
       // the global set.
       Sets.SetView<Integer> sv = Sets.difference(currentCounters, thisset);
       for (int counterId : sv) {
           if (thiscounters[counterId] != null) {
               thiscounters[counterId].enabled = true;
               thisset.add(counterId);
           }
       }
   }

   @Override
   public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
       if (!rci.allLevelsFound) {
           String missing = rci.levels[rci.foundUptoLevel];
           log.error("Cannot reset counter hierarchy - missing counter {}", missing);
           return;
       }
       // reset at this level
       allCounters[rci.ctrIds[rci.foundUptoLevel-1]].cvalue.set(0);
       // reset all levels below
       ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
       for (int index : resetIds) {
           allCounters[index].cvalue.set(0);
       }
   }

   @Override
   public void resetAllCounters() {
       RetCtrInfo rci = new RetCtrInfo();
       rci.levels = "".split("/");
       for (String moduleName : moduleCounters.keySet()) {
           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
           for (int index : resetIds) {
               allCounters[index].cvalue.set(0);
           }
       }
   }

   @Override
   public void resetAllModuleCounters(String moduleName) {
       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
       RetCtrInfo rci = new RetCtrInfo();
       rci.levels = "".split("/");

       if (target != null) {
           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
           for (int index : resetIds) {
               allCounters[index].cvalue.set(0);
           }
       } else {
           if (log.isDebugEnabled())
               log.debug("No module found with name {}", moduleName);
       }
   }

   @Override
   public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
       if (!rci.allLevelsFound) {
           String missing = rci.levels[rci.foundUptoLevel];
           log.error("Cannot enable counter - counter not found {}", missing);
           return;
       }
       // enable specific counter
       DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]];
       dc.cinfo.enabled = true;
       currentCounters.add(dc.cinfo.counterId);
   }

   @Override
   public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
       if (!rci.allLevelsFound) {
           String missing = rci.levels[rci.foundUptoLevel];
           log.error("Cannot disable counter - counter not found {}", missing);
           return;
       }
       // disable specific counter
       DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]];
       if (dc.cinfo.ctype == CounterType.COUNT_ON_DEMAND) {
           dc.cinfo.enabled = false;
           dc.cvalue.set(0);
           currentCounters.remove(dc.cinfo.counterId);
       }
   }

   @Override
   public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
                                                     String counterHierarchy) {
       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
       if (!rci.allLevelsFound) {
           String missing = rci.levels[rci.foundUptoLevel];
           log.error("Cannot fetch counter - counter not found {}", missing);
           return Collections.emptyList();
       }
       ArrayList<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
       // get counter and all below it
       DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]];
       dcilist.add(dc);
       ArrayList<Integer> belowIds = getHierarchyBelow(moduleName, rci);
       for (int index : belowIds) {
           dcilist.add(allCounters[index]);
       }
       return dcilist;
   }

   @Override
   public List<DebugCounterInfo> getAllCounterValues() {
       List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
       RetCtrInfo rci = new RetCtrInfo();
       rci.levels = "".split("/");

       for (String moduleName : moduleCounters.keySet()) {
           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
           for (int index : resetIds) {
               dcilist.add(allCounters[index]);
           }
       }
       return dcilist;
   }

   @Override
   public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
       List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
       RetCtrInfo rci = new RetCtrInfo();
       rci.levels = "".split("/");

       if (moduleCounters.containsKey(moduleName)) {
           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
           for (int index : resetIds) {
               dcilist.add(allCounters[index]);
           }
       }
       return dcilist;
   }

   @Override
   public boolean containsModuleCounterHierarchy(String moduleName,
                                                 String counterHierarchy) {
       if (!moduleCounters.containsKey(moduleName)) return false;
       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
       return rci.allLevelsFound;
   }

   @Override
   public boolean containsModuleName(String moduleName) {
       return  (moduleCounters.containsKey(moduleName)) ? true : false;
   }

   @Override
   public List<String> getModuleList() {
       List<String> retval = new ArrayList<String>();
       retval.addAll(moduleCounters.keySet());
       return retval;
   }

   @Override
   public List<String> getModuleCounterList(String moduleName) {
       if (!moduleCounters.containsKey(moduleName))
           return Collections.emptyList();

       List<String> retval = new ArrayList<String>();
       RetCtrInfo rci = new RetCtrInfo();
       rci.levels = "".split("/");

       ArrayList<Integer> cids = getHierarchyBelow(moduleName, rci);
       for (int index : cids) {
           retval.add(allCounters[index].cinfo.counterHierarchy);
       }
       return retval;
   }

   //*******************************
   //   Internal Methods
   //*******************************

   protected class RetCtrInfo {
       boolean allLevelsFound; // counter indices found all the way down the hierarchy
       boolean hierarchical; // true if counterHierarchy is hierarchical
       int foundUptoLevel;
       int[]  ctrIds;
       String[] levels;

       public RetCtrInfo() {
           ctrIds = new int[MAX_HIERARCHY];
           for (int i=0; i<MAX_HIERARCHY; i++) {
               ctrIds[i] = -1;
           }
       }

       @Override
       public boolean equals(Object oth) {
           if (!(oth instanceof RetCtrInfo)) return false;
           RetCtrInfo other = (RetCtrInfo)oth;
           if (other.allLevelsFound != this.allLevelsFound) return false;
           if (other.hierarchical != this.hierarchical) return false;
           if (other.foundUptoLevel != this.foundUptoLevel) return false;
           if (!Arrays.equals(other.ctrIds, this.ctrIds)) return false;
           if (!Arrays.equals(other.levels, this.levels)) return false;
           return true;
       }

   }

   protected RetCtrInfo getCounterId(String moduleName, String counterHierarchy) {
       RetCtrInfo rci = new RetCtrInfo();
       Map<String, CounterIndexStore> templevel = moduleCounters.get(moduleName);
       rci.levels = counterHierarchy.split("/");
       if (rci.levels.length > 1) rci.hierarchical = true;
       if (templevel == null) {
           log.error("moduleName {} does not exist in debugCounters", moduleName);
           return rci;
       }

       /*
       if (rci.levels.length > MAX_HIERARCHY) {
           // chop off all array elems greater that MAX_HIERARCHY
           String[] temp = new String[MAX_HIERARCHY];
           System.arraycopy(rci.levels, 0, temp, 0, MAX_HIERARCHY);
           rci.levels = temp;
       }
       */
       for (int i=0; i<rci.levels.length; i++) {
           if (templevel != null) {
               CounterIndexStore cis = templevel.get(rci.levels[i]) ;
               if (cis == null) {
                   // could not find counterHierarchy part at this level
                   break;
               } else {
                   rci.ctrIds[i] = cis.index;
                   templevel = cis.nextLevel;
                   rci.foundUptoLevel++;
                   if (i == rci.levels.length-1) {
                       rci.allLevelsFound = true;
                   }
               }
           } else {
               // there are no more levels, which means that some part of the
               // counterHierarchy has no corresponding map
               break;
           }
       }
       return rci;
   }

   protected void addToModuleCounterHierarchy(String moduleName, int counterId,
                                            RetCtrInfo rci) {
       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
       if (target == null) return;
       CounterIndexStore cis = null;

       for (int i=0; i<rci.foundUptoLevel; i++) {
           cis = target.get(rci.levels[i]);
           target = cis.nextLevel;
       }
       if (cis != null) {
           if (cis.nextLevel == null)
               cis.nextLevel = new ConcurrentHashMap<String, CounterIndexStore>();
           cis.nextLevel.put(rci.levels[rci.foundUptoLevel],
                             new CounterIndexStore(counterId, null));
       } else {
           target.put(rci.levels[rci.foundUptoLevel],
                      new CounterIndexStore(counterId, null));
       }
   }

   // given a partial hierarchical counter, return the rest of the hierarchy
   protected ArrayList<Integer> getHierarchyBelow(String moduleName, RetCtrInfo rci) {
       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
       CounterIndexStore cis = null;
       ArrayList<Integer> retval = new ArrayList<Integer>();
       if (target == null) return retval;

       // get to the level given
       for (int i=0; i<rci.foundUptoLevel; i++) {
           cis = target.get(rci.levels[i]);
           target = cis.nextLevel;
       }

       if (target == null || rci.foundUptoLevel == MAX_HIERARCHY) {
           // no more levels
           return retval;
       } else {
           // recursively get all ids
           getIdsAtLevel(target, retval, rci.foundUptoLevel+1);
       }

       return retval;
   }

   protected void getIdsAtLevel(Map<String, CounterIndexStore> hcy,
                                ArrayList<Integer> retval, int level) {
       if (level > MAX_HIERARCHY) return;
       if (hcy == null || retval == null) return;

       // Can return the counter names as well but for now ids are enough.
       for (CounterIndexStore cistemp : hcy.values()) {
           retval.add(cistemp.index); // value at this level
           if (cistemp.nextLevel != null) {
               getIdsAtLevel(cistemp.nextLevel, retval, level+1);
           }
       }
   }

   protected void printAllCounterIds() {
       log.info("<moduleCounterHierarchy>");
       Set<String> keys = moduleCounters.keySet();
       for (String key : keys) {
           log.info("ModuleName: {}", key);
           Map<String, CounterIndexStore> lev1 = moduleCounters.get(key);
           for (String key1 : lev1.keySet()) {
               CounterIndexStore cis1 = lev1.get(key1);
               log.info(" L1 {}:{}", key1, new Object[] {cis1.index, cis1.nextLevel});
               if (cis1.nextLevel != null) {
                   Map<String, CounterIndexStore> lev2 = cis1.nextLevel;
                   for (String key2 : lev2.keySet()) {
                       CounterIndexStore cis2 = lev2.get(key2);
                       log.info("  L2 {}:{}", key2, new Object[] {cis2.index,
                                                                  cis2.nextLevel});
                       if (cis2.nextLevel != null) {
                           Map<String, CounterIndexStore> lev3 = cis2.nextLevel;
                           for (String key3 : lev3.keySet()) {
                               CounterIndexStore cis3 = lev3.get(key3);
                               log.info("   L3 {}:{}", key3, new Object[] {cis3.index,
                                                                          cis3.nextLevel});
                           }
                       }
                   }
               }
           }
       }
       log.info("<\\moduleCounterHierarchy>");
   }

   //*******************************
   //   IFloodlightModule
   //*******************************

   @Override
   public Collection<Class<? extends IFloodlightService>> getModuleServices() {
       Collection<Class<? extends IFloodlightService>> l =
               new ArrayList<Class<? extends IFloodlightService>>();
       l.add(IDebugCounterService.class);
       return l;
   }

   @Override
   public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
       Map<Class<? extends IFloodlightService>, IFloodlightService> m =
               new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
       m.put(IDebugCounterService.class, this);
       return m;
   }

   @Override
   public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
       ArrayList<Class<? extends IFloodlightService>> deps =
               new ArrayList<Class<? extends IFloodlightService>>();
       deps.add(IRestApiService.class);
       return deps;
   }

   @Override
   public void init(FloodlightModuleContext context) throws FloodlightModuleException {

   }

   @Override
   public void startUp(FloodlightModuleContext context) {
       IRestApiService restService =
               context.getServiceImpl(IRestApiService.class);
       restService.addRestletRoutable(new DebugCounterRoutable());
   }

}
