package net.floodlightcontroller.debugevent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

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

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.debugevent.web.DebugEventRoutable;
import net.floodlightcontroller.restserver.IRestApiService;

import com.google.common.collect.Sets;
/**
 * This class implements a central store for all events used for debugging the
 * system. The basic idea is that given the functionality provided by this class,
 * it should be unnecessary to resort to scraping through system DEBUG/TRACE logs
 * to understand behavior in a running system.
 *
 * @author saurav
 */
public class DebugEvent implements IFloodlightModule, IDebugEventService {
    protected static Logger log = LoggerFactory.getLogger(DebugEvent.class);

    /**
     *  Every registered event type gets an event id, the value for which is obtained
     *  while holding the lock.
     */
    protected int eventIdCounter = 0;
    protected Object eventIdLock = new Object();

    private static final int PCT_LOCAL_CAP = 10; // % of global capacity
    private static final int MIN_LOCAL_CAPACITY = 10; //elements

    /**
     * Event Information
     */
    public class EventInfo {
        int eventId;
        boolean enabled;
        int bufferCapacity;
        EventType etype;
        String eventDesc;
        String eventName;
        String moduleName;
        String moduleEventName;
        Class<?> eventClass;
        String[] metaData;

        public EventInfo(int eventId, boolean enabled, int bufferCapacity,
                         EventType etype, Class<?> eventClass, String eventDesc,
                         String eventName, String moduleName, String... metaData) {
            this.enabled = enabled;
            this.eventId = eventId;
            this.bufferCapacity = bufferCapacity;
            this.etype = etype;
            this.eventClass = eventClass;
            this.eventDesc = eventDesc;
            this.eventName = eventName;
            this.moduleName = moduleName;
            this.moduleEventName = moduleName + "/" + eventName;
            this.metaData = metaData;
        }

        public int getEventId() { return eventId; }
        public boolean isEnabled() { return enabled; }
        public int getBufferCapacity() { return bufferCapacity; }
        public EventType getEtype() { return etype; }
        public String getEventDesc() { return eventDesc; }
        public String getEventName() { return eventName; }
        public String getModuleName() { return moduleName; }
        public String getModuleEventName() { return moduleEventName; }
        public String[] getMetaData() { return metaData; }
    }

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

    /**
     * Event history for a particular event-id is stored in a circular buffer
     */
    protected class DebugEventHistory {
        EventInfo einfo;
        CircularBuffer<Event> eventBuffer;

        public DebugEventHistory(EventInfo einfo, int capacity) {
            this.einfo = einfo;
            this.eventBuffer = new CircularBuffer<Event>(capacity);
        }
    }

    /**
     * Global storage for all event types and their corresponding event buffers.
     * A particular event type is accessed by directly indexing into the array
     * with the corresponding event-id.
     */
    protected DebugEventHistory[] allEvents =
                    new DebugEventHistory[MAX_EVENTS];

    /**
     * Global storage for all event ids registered for a module. The map is indexed
     * by the module name and event name and returns the event-ids that correspond to the
     * event types registered by that module (for example module 'linkdiscovery'
     * may register events that have ids 0 and 1 that correspond to link up/down
     * events, and receiving malformed LLDP packets, respectively).
     */
    protected ConcurrentHashMap<String, ConcurrentHashMap<String, Integer>>
        moduleEvents = new ConcurrentHashMap<String,
                                ConcurrentHashMap<String, Integer>>();

    /**
     * A collection of event ids that are currently enabled for logging
     */
    protected Set<Integer> currentEvents = Collections.newSetFromMap(
                                       new ConcurrentHashMap<Integer,Boolean>());

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

    /**
     * Thread local storage for events
     */
    protected class LocalEventHistory {
        int nextIndex;
        int maxCapacity;
        boolean enabled;
        ArrayList<Event> eventList;

        public LocalEventHistory(boolean enabled, int maxCapacity) {
            this.nextIndex = 0;
            this.maxCapacity = maxCapacity;
            this.enabled = enabled;
            this.eventList = new ArrayList<Event>();
        }
    }

    /**
     * Thread local event buffers used for maintaining event history local to
     * a thread. Eventually this locally maintained information is flushed
     * into the global event buffers.
     */
    protected final ThreadLocal<LocalEventHistory[]> threadlocalEvents =
            new ThreadLocal<LocalEventHistory[]>() {
        @Override
        protected LocalEventHistory[] initialValue() {
            return new LocalEventHistory[MAX_EVENTS];
        }
    };

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

    //*******************************
    //   IEventUpdater
    //*******************************

    protected class EventUpdaterImpl<T> implements IEventUpdater<T> {
        private final int eventId;

        public EventUpdaterImpl(int evId) {
            this.eventId = evId;
        }

        @Override
        public void updateEventNoFlush(Object event) {
            if (!validEventId()) return;
            updateEvent(eventId, false, event);
        }

        @Override
        public void updateEventWithFlush(Object event) {
            if (!validEventId()) return;
            updateEvent(eventId, true, event);
        }

        private boolean validEventId() {
            if (eventId < 0 || eventId >= MAX_EVENTS) {
                throw new IllegalStateException();
            }
            return true;
        }

    }

    //*******************************
    //   IDebugEventService
    //*******************************

    @Override
    public <T> IEventUpdater<T> registerEvent(String moduleName, String eventName,
                                              String eventDescription, EventType et,
                                              Class<T> eventClass, int bufferCapacity,
                                              String... metaData) throws MaxEventsRegistered {
        int eventId = -1;
        synchronized (eventIdLock) {
             eventId = Integer.valueOf(eventIdCounter++);
        }
        if (eventId > MAX_EVENTS-1) {
            throw new MaxEventsRegistered();
        }

        // register event id for moduleName
        if (!moduleEvents.containsKey(moduleName)) {
            moduleEvents.put(moduleName, new ConcurrentHashMap<String, Integer>());
        }
        if (!moduleEvents.get(moduleName).containsKey(eventName)) {
            moduleEvents.get(moduleName).put(eventName, new Integer(eventId));
        } else {
            int existingEventId = moduleEvents.get(moduleName).get(eventName);
            log.error("Duplicate event registration for moduleName {} eventName {}",
                      moduleName, eventName);
            return new EventUpdaterImpl<T>(existingEventId);
        }

        // create storage for event-type
        boolean enabled = (et == EventType.ALWAYS_LOG) ? true : false;
        EventInfo ei = new EventInfo(eventId, enabled, bufferCapacity,
                                     et, eventClass, eventDescription, eventName,
                                     moduleName, metaData);
        allEvents[eventId] = new DebugEventHistory(ei, bufferCapacity);
        if (enabled) {
            currentEvents.add(eventId);
        }

        return new EventUpdaterImpl<T>(eventId);
    }

    private void updateEvent(int eventId, boolean flushNow, Object eventData) {
        if (eventId < 0 || eventId > MAX_EVENTS-1) return;

        LocalEventHistory[] thishist = this.threadlocalEvents.get();
        if (thishist[eventId] == null) {
            // seeing this event for the first time in this thread - create local
            // store by consulting global store
            DebugEventHistory de = allEvents[eventId];
            if (de != null) {
                boolean enabled = de.einfo.enabled;
                int localCapacity = de.einfo.bufferCapacity * PCT_LOCAL_CAP/ 100;
                if (localCapacity < 10)  localCapacity = MIN_LOCAL_CAPACITY;
                thishist[eventId] = new LocalEventHistory(enabled, localCapacity);
                if (enabled) {
                    Set<Integer> thisset = this.threadlocalCurrentEvents.get();
                    thisset.add(eventId);
                }
            } else {
                log.error("updateEvent seen locally for event {} but no global"
                          + "storage exists for it yet .. not updating", eventId);
                return;
            }
        }

        // update local store if enabled locally for updating
        LocalEventHistory le = thishist[eventId];
        if (le.enabled) {
            long timestamp = System.currentTimeMillis();
            long thisthread = Thread.currentThread().getId();
            String thisthreadname = Thread.currentThread().getName();
            if (le.nextIndex < le.eventList.size()) {
                if (le.eventList.get(le.nextIndex) == null) {
                    le.eventList.set(le.nextIndex, new Event(timestamp, thisthread,
                                                             thisthreadname,
                                                             eventData));
                } else {
                    Event e = le.eventList.get(le.nextIndex);
                    e.timestamp = timestamp;
                    e.threadId = thisthread;
                    e.threadName = thisthreadname;
                    e.eventData = eventData;
                    e.nullifyCachedFormattedEvent();
                }
            } else {
                le.eventList.add(new Event(timestamp, thisthread, thisthreadname, eventData));
            }
            le.nextIndex++;

            if (le.nextIndex >= le.maxCapacity || flushNow) {
                // flush this buffer now
                DebugEventHistory de = allEvents[eventId];
                if (de.einfo.enabled) {
                    le.eventList = de.eventBuffer.addAll(le.eventList, le.nextIndex);
                } else {
                    // global buffer is disabled - don't flush, disable locally
                    le.enabled = false;
                    Set<Integer> thisset = this.threadlocalCurrentEvents.get();
                    thisset.remove(eventId);
                }
                le.nextIndex = 0;
            }
        }
    }

    @Override
    public void flushEvents() {
        LocalEventHistory[] thishist = this.threadlocalEvents.get();
        Set<Integer> thisset = this.threadlocalCurrentEvents.get();
        ArrayList<Integer> temp = new ArrayList<Integer>();

        for (int eventId : thisset) {
            LocalEventHistory le = thishist[eventId];
            if (le != null && le.nextIndex > 0) {
                // flush this buffer now
                DebugEventHistory de = allEvents[eventId];
                if (de.einfo.enabled) {
                    le.eventList = de.eventBuffer.addAll(le.eventList, le.nextIndex);
                } else {
                    // global buffer is disabled - don't flush, disable locally
                    le.enabled = false;
                    temp.add(eventId);
                }
                le.nextIndex = 0;
            }
        }
        for (int eId : temp)
            thisset.remove(eId);

        // sync thread local currently enabled set of eventIds with global set.
        Sets.SetView<Integer> sv = Sets.difference(currentEvents, thisset);
        for (int eventId : sv) {
            if (thishist[eventId] != null) {
                thishist[eventId].enabled = true;
                thisset.add(eventId);
            }
        }

    }

    @Override
    public boolean containsModuleEventName(String moduleName, String eventName) {
        if (!moduleEvents.containsKey(moduleName)) return false;
        if (moduleEvents.get(moduleName).containsKey(eventName)) return true;
        return false;
    }

    @Override
    public boolean containsModuleName(String moduleName) {
        return moduleEvents.containsKey(moduleName);
    }

    @Override
    public List<DebugEventInfo> getAllEventHistory() {
        List<DebugEventInfo> moduleEventList = new ArrayList<DebugEventInfo>();
        for (Map<String, Integer> modev : moduleEvents.values()) {
            for (int eventId : modev.values()) {
                DebugEventHistory de = allEvents[eventId];
                if (de != null) {
                    List<Map<String,String>> ret = new ArrayList<Map<String,String>>();
                    for (Event e : de.eventBuffer) {
                        ret.add(e.getFormattedEvent(de.einfo.eventClass,
                                                    de.einfo.moduleEventName));
                    }
                    moduleEventList.add(new DebugEventInfo(de.einfo, ret));
                }
            }
        }
        return moduleEventList;
    }

    @Override
    public List<DebugEventInfo> getModuleEventHistory(String moduleName) {
        if (!moduleEvents.containsKey(moduleName)) return Collections.emptyList();
        List<DebugEventInfo> moduleEventList = new ArrayList<DebugEventInfo>();
        for (int eventId : moduleEvents.get(moduleName).values()) {
            DebugEventHistory de = allEvents[eventId];
            if (de != null) {
                List<Map<String,String>> ret = new ArrayList<Map<String,String>>();
                for (Event e : de.eventBuffer) {
                    ret.add(e.getFormattedEvent(de.einfo.eventClass,
                                                de.einfo.moduleEventName));
                }
                moduleEventList.add(new DebugEventInfo(de.einfo, ret));
            }
        }
        return moduleEventList;
    }

    @Override
    public DebugEventInfo getSingleEventHistory(String moduleName, String eventName,
                                                int last) {
        if (!moduleEvents.containsKey(moduleName)) return null;
        Integer eventId = moduleEvents.get(moduleName).get(eventName);
        if (eventId == null) return null;
        DebugEventHistory de = allEvents[eventId];
        if (de != null) {
            int num = 1;
            List<Map<String,String>> ret = new ArrayList<Map<String,String>>();
            for (Event e : de.eventBuffer) {
                if (num > last)
                    break;
                Map<String, String> temp = e.getFormattedEvent(de.einfo.eventClass,
                                                               de.einfo.moduleEventName);
                temp.put("#", String.valueOf(num++));
                ret.add(temp);
            }
            return new DebugEventInfo(de.einfo, ret);
        }
        return null;
    }

    @Override
    public void resetAllEvents() {
        for (Map<String, Integer> eventMap : moduleEvents.values()) {
            for (Integer evId : eventMap.values()) {
                allEvents[evId].eventBuffer.clear();
            }
        }
    }

    @Override
    public void resetAllModuleEvents(String moduleName) {
        if (!moduleEvents.containsKey(moduleName)) return;
        Map<String, Integer> modEvents = moduleEvents.get(moduleName);
        for (Integer evId : modEvents.values()) {
            allEvents[evId].eventBuffer.clear();
        }
    }

    @Override
    public void resetSingleEvent(String moduleName, String eventName) {
        if (!moduleEvents.containsKey(moduleName)) return;
        Integer eventId = moduleEvents.get(moduleName).get(eventName);
        if (eventId == null) return;
        DebugEventHistory de = allEvents[eventId];
        if (de != null) {
            de.eventBuffer.clear();
        }
    }

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

    @Override
    public List<String> getModuleEventList(String moduleName) {
        if (!moduleEvents.containsKey(moduleName))
            return Collections.emptyList();
        List<String> el = new ArrayList<String>();
        el.addAll(moduleEvents.get(moduleName).keySet());
        return el;
    }

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

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l =
                new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IDebugEventService.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(IDebugEventService.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)
            throws FloodlightModuleException {
        IRestApiService restService =
                context.getServiceImpl(IRestApiService.class);
        restService.addRestletRoutable(new DebugEventRoutable());
        DebugEventAppender.setDebugEventServiceImpl(this);
    }

}
