package org.onlab.onos.of.controller.impl.debugcounter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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;



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

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

    /**
     * The counter value.
     */
    protected static 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 this.metaData.clone(); }
    }

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

    /**
     * Counter info for a debug counter.
     */
    public static 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.
     */
    private static final 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 static 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 static 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();
        }

        /**
         * Checks if this is a valid counter.
         * @return true if the counter id is valid
         */
        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 CounterException {
       // 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) {
           StringBuilder sb = new StringBuilder();
           for (int i = 0; i <= rci.foundUptoLevel; i++) {
               sb.append(rci.levels[i]);
           }
           String needToRegister = sb.toString();
           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 int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + getOuterType().hashCode();
        result = prime * result + (allLevelsFound ? 1231 : 1237);
        result = prime * result + Arrays.hashCode(ctrIds);
        result = prime * result + foundUptoLevel;
        result = prime * result + (hierarchical ? 1231 : 1237);
        result = prime * result + Arrays.hashCode(levels);
        return result;
    }

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

    private DebugCounter getOuterType() {
        return DebugCounter.this;
    }



   }

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

}
