package org.helioviewer.plugins.eveplugin.events.data;

import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;

import org.helioviewer.base.logging.Log;
import org.helioviewer.base.math.Interval;
import org.helioviewer.jhv.data.container.JHVEventContainer;
import org.helioviewer.jhv.data.container.JHVEventHandler;
import org.helioviewer.jhv.data.datatype.event.JHVEvent;
import org.helioviewer.plugins.eveplugin.EVEState;
import org.helioviewer.plugins.eveplugin.controller.ZoomController;
import org.helioviewer.plugins.eveplugin.controller.ZoomControllerListener;
import org.helioviewer.plugins.eveplugin.settings.EVEAPI.API_RESOLUTION_AVERAGES;

/**
 * Requests events from the JHVEventContainer if the selected interval or
 * available interval changes.
 * 
 * @author Bram Bourgoignie (Bram.Bourgoignie@oma.be)
 * 
 */
public class EventRequester implements ZoomControllerListener, JHVEventHandler {

    /** Singleton instance of the event requester */
    private static EventRequester singletonInstance;

    /** Instance of the event container */
    private final JHVEventContainer eventContainer;

    /** the selected interval */
    private Interval<Date> selectedInterval;

    /** the available interval */
    private Interval<Date> availableInterval;

    /** The listeners */
    private final List<EventRequesterListener> listeners;

    /**
     * Private default constructor.
     * 
     */
    private EventRequester() {
        eventContainer = JHVEventContainer.getSingletonInstance();
        ZoomController.getSingletonInstance().addZoomControllerListener(this);
        availableInterval = new Interval<Date>(new Date(), new Date());
        selectedInterval = new Interval<Date>(new Date(), new Date());
        listeners = new ArrayList<EventRequesterListener>();
    }

    /**
     * Gets the singleton instance of the EventRequester.
     * 
     * @return The singleton instance
     */
    public static EventRequester getSingletonInstance() {
        if (singletonInstance == null) {
            singletonInstance = new EventRequester();
        }
        return singletonInstance;
    }

    /**
     * Adds a new IncomingEventHandlerListener.
     * 
     * @param listener
     *            the listener to add
     */
    public void addListener(EventRequesterListener listener) {
        listeners.add(listener);
    }

    /**
     * Removes an IncomingEventHandlerListener.
     * 
     * @param listener
     *            the listener to remove
     */
    public void removeListener(EventRequesterListener listener) {
        listeners.remove(listener);
    }

    @Override
    public void availableIntervalChanged(final Interval<Date> newInterval) {
        availableInterval = newInterval;
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                eventContainer.requestForInterval(newInterval.getStart(), newInterval.getEnd(), EventRequester.this);
            }
        });
    }

    @Override
    public void selectedIntervalChanged(Interval<Date> newInterval, boolean keepFullValueSpace) {
        selectedInterval = newInterval;
        // Log.info("selectedInterval : " + newInterval);
        if (!EVEState.getSingletonInstance().isMouseTimeIntervalDragging()) {
            EventQueue.invokeLater(new Runnable() {
                private Interval<Date> interval;
                private JHVEventHandler eventHandler;

                public Runnable init(Interval<Date> interval, JHVEventHandler eventHandler) {
                    this.interval = interval;
                    this.eventHandler = eventHandler;
                    return this;
                }

                @Override
                public void run() {
                    // long start = System.currentTimeMillis();
                    JHVEventContainer.getSingletonInstance().requestForInterval(interval.getStart(), interval.getEnd(), eventHandler);
                    // Log.debug("selectedIntervalChanged" +
                    // (System.currentTimeMillis() - start));
                }

            }.init(newInterval, this));
        } else {
            // Log.info("Mouse dragging");
        }
    }

    @Override
    public void selectedResolutionChanged(API_RESOLUTION_AVERAGES newResolution) {

    }

    @Override
    public void newEventsReceived(final Map<String, NavigableMap<Date, NavigableMap<Date, List<JHVEvent>>>> eventList) {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                // Log.debug("new events received " + eventList.size());
                // long start = System.currentTimeMillis();
                fireNewEventsReceived(eventList);
                // Log.debug("newEventsReceived time : " +
                // (System.currentTimeMillis() - start));
            }

        });

    }

    @Override
    public void cacheUpdated() {
        EventQueue.invokeLater((new Runnable() {

            private Interval<Date> selectedInterval;
            private JHVEventHandler eventHandler;

            public Runnable init(Interval<Date> selectedInterval, JHVEventHandler eventHandler) {
                this.selectedInterval = selectedInterval;
                this.eventHandler = eventHandler;
                return this;
            }

            @Override
            public void run() {
                // Log.debug("Request for interval");
                long start = System.currentTimeMillis();
                eventContainer.requestForInterval(selectedInterval.getStart(), selectedInterval.getEnd(), eventHandler);
                Log.debug("cache updated time: " + (System.currentTimeMillis() - start));
            }

        }).init(selectedInterval, this));

    }

    private void fireNewEventsReceived(Map<String, NavigableMap<Date, NavigableMap<Date, List<JHVEvent>>>> events) {
        for (EventRequesterListener l : listeners) {
            l.newEventsReceived(events);
        }
    }
}

@@ -209,49 +209,8 @@
 p;%0A%0A
-import org.helioviewer.base.logging.Log;%0A
 impo
@@ -4620,289 +4620,39 @@
     
-// Log.debug(%22new events received %22 + eventList.size());%0A                // long start = System.currentTimeMillis();%0A                fireNewEventsReceived(eventList);%0A                // Log.debug(%22newEventsReceived time : %22 +%0A                // (System.currentTimeMillis() - start)
+fireNewEventsReceived(eventList
 );%0A 
@@ -5194,119 +5194,8 @@
 ) %7B%0A
-                // Log.debug(%22Request for interval%22);%0A                long start = System.currentTimeMillis();%0A
     
@@ -5315,98 +5315,8 @@
 r);%0A
-                Log.debug(%22cache updated time: %22 + (System.currentTimeMillis() - start));%0A
     

Remove overhead