/*
 * Copyright 2014-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.event.impl;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.SharedExecutors;
import org.onosproject.event.AbstractEvent;
import org.onosproject.event.DefaultEventSinkRegistry;
import org.onosproject.event.Event;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.EventSink;
import org.slf4j.Logger;

import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;

import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.*;
/**
 * Simple implementation of an event dispatching service.
 */
@Component(immediate = true)
@Service
public class CoreEventDispatcher extends DefaultEventSinkRegistry
        implements EventDeliveryService {

    private final Logger log = getLogger(getClass());

    // Default number of millis a sink can take to process an event.
    private static final long DEFAULT_EXECUTE_MS = 5_000; // ms
    private static final long WATCHDOG_MS = 250; // ms

    private final BlockingQueue<Event> events = new LinkedBlockingQueue<>();

    private final ExecutorService executor =
            newSingleThreadExecutor(groupedThreads("onos/event", "dispatch-%d", log));

    @SuppressWarnings("unchecked")
    private static final Event KILL_PILL = new AbstractEvent(null, 0) {
    };

    private DispatchLoop dispatchLoop;
    private long maxProcessMillis = DEFAULT_EXECUTE_MS;

    // Means to detect long-running sinks
    private TimerTask watchdog;
    private EventSink lastSink;
    private long lastStart = 0;
    private Future<?> dispatchFuture;

    @Override
    public void post(Event event) {
        if (!events.add(event)) {
            log.error("Unable to post event {}", event);
        }
    }

    @Activate
    public void activate() {
        dispatchLoop = new DispatchLoop();
        dispatchFuture = executor.submit(dispatchLoop);
        watchdog = new Watchdog();
        SharedExecutors.getTimer().schedule(watchdog, WATCHDOG_MS, WATCHDOG_MS);
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        dispatchLoop.stop();
        watchdog.cancel();
        post(KILL_PILL);
        log.info("Stopped");
    }

    @Override
    public void setDispatchTimeLimit(long millis) {
        checkPermission(EVENT_WRITE);
        checkArgument(millis >= WATCHDOG_MS,
                      "Time limit must be greater than %s", WATCHDOG_MS);
        maxProcessMillis = millis;
    }

    @Override
    public long getDispatchTimeLimit() {
        checkPermission(EVENT_READ);
        return maxProcessMillis;
    }

    // Auxiliary event dispatching loop that feeds off the events queue.
    private class DispatchLoop implements Runnable {
        private volatile boolean stopped;

        @Override
        public void run() {
            stopped = false;
            log.info("Dispatch loop initiated");
            while (!stopped) {
                try {
                    // Fetch the next event and if it is the kill-pill, bail
                    Event event = events.take();
                    if (event == KILL_PILL) {
                        break;
                    }
                    process(event);
                } catch (InterruptedException e) {
                    log.warn("Dispatch loop interrupted");
                } catch (Exception | Error e) {
                    log.warn("Error encountered while dispatching event:", e);
                }
            }
            log.info("Dispatch loop terminated");
        }

        // Locate the sink for the event class and use it to process the event
        @SuppressWarnings("unchecked")
        private void process(Event event) {
            EventSink sink = getSink(event.getClass());
            if (sink != null) {
                lastSink = sink;
                lastStart = System.currentTimeMillis();
                sink.process(event);
                lastStart = 0;
            } else {
                log.warn("No sink registered for event class {}",
                         event.getClass().getName());
            }
        }

        void stop() {
            stopped = true;
        }
    }

    // Monitors event sinks to make sure none take too long to execute.
    private class Watchdog extends TimerTask {
        @Override
        public void run() {
            long delta = System.currentTimeMillis() - lastStart;
            if (lastStart > 0 && delta > maxProcessMillis) {
                lastStart = 0;
                log.warn("Event sink {} exceeded execution time limit: {} ms; spawning new dispatch loop",
                          lastSink.getClass().getName(), delta);

                // Notify the sink that it has exceeded its time limit.
                lastSink.onProcessLimit();

                // Cancel the old dispatch loop and submit a new one.
                dispatchLoop.stop();
                dispatchLoop = new DispatchLoop();
                dispatchFuture.cancel(true);
                dispatchFuture = executor.submit(dispatchLoop);
            }
        }
    }
}
