/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 com.googlecode.android_scripting.facade;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.event.Event;
import com.googlecode.android_scripting.event.EventObserver;
import com.googlecode.android_scripting.future.FutureResult;
import com.googlecode.android_scripting.jsonrpc.JsonBuilder;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcDefault;
import com.googlecode.android_scripting.rpc.RpcDeprecated;
import com.googlecode.android_scripting.rpc.RpcName;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;

import org.json.JSONException;

import java.util.HashMap;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

/**
 * Manage the event queue. <br>
 * <br>
 * <b>Usage Notes:</b><br>
 * EventFacade APIs interact with the Event Queue (a data buffer containing up to 1024 event
 * entries).<br>
 * Events are automatically entered into the Event Queue following API calls such as startSensing()
 * and startLocating().<br>
 * The Event Facade provides control over how events are entered into (and removed from) the Event
 * Queue.<br>
 * The Event Queue provides a useful means of recording background events (such as sensor data) when
 * the phone is busy with foreground activities.
 */
public class EventFacade extends RpcReceiver {
    /**
     * The maximum length of the event queue. Old events will be discarded when this limit is
     * exceeded.
     */
    private static final int MAX_QUEUE_SIZE = 1024;
    private final Queue<Event> mEventQueue = new ConcurrentLinkedQueue<Event>();
    private final CopyOnWriteArrayList<EventObserver> mGlobalEventObservers =
            new CopyOnWriteArrayList<EventObserver>();
    private final Multimap<String, EventObserver> mNamedEventObservers = Multimaps
            .synchronizedListMultimap(ArrayListMultimap.<String, EventObserver>create());
    private final HashMap<String, BroadcastListener> mBroadcastListeners =
            new HashMap<String, BroadcastListener>();
    private final Context mContext;

    public EventFacade(FacadeManager manager) {
        super(manager);
        mContext = manager.getService().getApplicationContext();
        Log.v("Creating new EventFacade Instance()");
    }

    /**
     * Example (python): droid.eventClearBuffer()
     */
    @Rpc(description = "Clears all events from the event buffer.")
    public void eventClearBuffer() {
        mEventQueue.clear();
    }

    /**
     * Registers a listener for a new broadcast signal
     */
    @Rpc(description = "Registers a listener for a new broadcast signal")
    public boolean eventRegisterForBroadcast(
            @RpcParameter(name = "category") String category,
            @RpcParameter(name = "enqueue",
                    description = "Should this events be added to the event queue or only dispatched") @RpcDefault(value = "true") Boolean enqueue) {
        if (mBroadcastListeners.containsKey(category)) {
            return false;
        }

        BroadcastListener b = new BroadcastListener(this, enqueue.booleanValue());
        IntentFilter c = new IntentFilter(category);
        mContext.registerReceiver(b, c);
        mBroadcastListeners.put(category, b);

        return true;
    }

    @Rpc(description = "Stop listening for a broadcast signal")
    public void eventUnregisterForBroadcast(
            @RpcParameter(name = "category") String category) {
        if (!mBroadcastListeners.containsKey(category)) {
            return;
        }

        mContext.unregisterReceiver(mBroadcastListeners.get(category));
        mBroadcastListeners.remove(category);
    }

    @Rpc(description = "Lists all the broadcast signals we are listening for")
    public Set<String> eventGetBrodcastCategories() {
        return mBroadcastListeners.keySet();
    }

    /**
     * Actual data returned in the map will depend on the type of event.
     * <p>
     * <pre>
     * Example (python):
     *     import android, time
     *     droid = android.Android()
     *     droid.startSensing()
     *     time.sleep(1)
     *     droid.eventClearBuffer()
     *     time.sleep(1)
     *     e = eventPoll(1).result
     *     event_entry_number = 0
     *     x = e[event_entry_ number]['data']['xforce']
     * </pre>
     * <p>
     * e has the format:<br>
     * [{u'data': {u'accuracy': 0, u'pitch': -0.48766891956329345, u'xmag': -5.6875, u'azimuth':
     * 0.3312483489513397, u'zforce': 8.3492730000000002, u'yforce': 4.5628165999999997, u'time':
     * 1297072704.813, u'ymag': -11.125, u'zmag': -42.375, u'roll': -0.059393649548292161,
     * u'xforce': 0.42223078000000003}, u'name': u'sensors', u'time': 1297072704813000L}]<br>
     * x has the string value of the x force data (0.42223078000000003) at the time of the event
     * entry. </pre>
     */

    @Rpc(description = "Returns and removes the oldest n events (i.e. location or sensor update, etc.) from the event buffer.",
            returns = "A List of Maps of event properties.")
    public List<Event> eventPoll(
            @RpcParameter(name = "number_of_events") @RpcDefault("1") Integer number_of_events) {
        List<Event> events = Lists.newArrayList();
        for (int i = 0; i < number_of_events; i++) {
            Event event = mEventQueue.poll();
            if (event == null) {
                break;
            }
            events.add(event);
        }
        return events;
    }

    @Rpc(description = "Blocks until an event with the supplied name occurs. Event is removed from the buffer if removeEvent is True.",
            returns = "Map of event properties.")
    public Event eventWaitFor(
            @RpcParameter(name = "eventName") final String eventName,
            @RpcParameter(name = "removeEvent") final Boolean removeEvent,
            @RpcParameter(name = "timeout", description = "the maximum time to wait (in ms)") @RpcOptional Integer timeout)
            throws InterruptedException {
        Event result = null;
        final FutureResult<Event> futureEvent;
        synchronized (mEventQueue) { // First check to make sure it isn't already there
            for (Event event : mEventQueue) {
                if (event.getName().equals(eventName)) {
                    result = event;
                    if (removeEvent)
                        mEventQueue.remove(event);
                    return result;
                }
            }
            futureEvent = new FutureResult<Event>();
            addNamedEventObserver(eventName, new EventObserver() {
                @Override
                public void onEventReceived(Event event) {
                    if (event.getName().equals(eventName)) {
                        synchronized (futureEvent) {
                            if (!futureEvent.isDone()) {
                                futureEvent.set(event);
                                // TODO: Remove log.
                                Log.v(String.format("Removing observer (%s) got event  (%s)",
                                        this,
                                        event));
                                removeEventObserver(this);
                            }
                            if (removeEvent)
                                mEventQueue.remove(event);
                        }
                    }
                }
            });
        }
        if (futureEvent != null) {
            if (timeout != null) {
                result = futureEvent.get(timeout, TimeUnit.MILLISECONDS);
            } else {
                result = futureEvent.get();
            }
        }
        return result;
    }

    @Rpc(description = "Blocks until an event occurs. The returned event is removed from the buffer.",
            returns = "Map of event properties.")
    public Event eventWait(
            @RpcParameter(name = "timeout", description = "the maximum time to wait") @RpcOptional Integer timeout)
            throws InterruptedException {
        Event result = null;
        final FutureResult<Event> futureEvent = new FutureResult<Event>();
        EventObserver observer;
        synchronized (mEventQueue) { // Anything in queue?
            if (mEventQueue.size() > 0) {
                return mEventQueue.poll(); // return it.
            }
            observer = new EventObserver() {
                @Override
                public void onEventReceived(Event event) { // set up observer for any events.
                    synchronized (futureEvent) {
                        if (!futureEvent.isDone()) {
                            futureEvent.set(event);
                            // TODO: Remove log.
                            Log.v(String.format("onEventReceived for event (%s)", event));
                        }
                    }
                }
            };
            addGlobalEventObserver(observer);
        }
        if (timeout != null) {
            result = futureEvent.get(timeout, TimeUnit.MILLISECONDS);
        } else {
            result = futureEvent.get();
        }
        if (result != null) {
            mEventQueue.remove(result);
        }
        // TODO: Remove log.
        Log.v(String.format("Removing observer (%s) got event  (%s)", observer, result));
        if (observer != null) {
            removeEventObserver(observer); // Make quite sure this goes away.
        }
        return result;
    }

    /**
     * <pre>
     * Example:
     *   import android
     *   from datetime import datetime
     *   droid = android.Android()
     *   t = datetime.now()
     *   droid.eventPost('Some Event', t)
     * </pre>
     */
    @Rpc(description = "Post an event to the event queue.")
    public void eventPost(
            @RpcParameter(name = "name", description = "Name of event") String name,
            @RpcParameter(name = "data", description = "Data contained in event.") String data,
            @RpcParameter(name = "enqueue",
                    description = "Set to False if you don't want your events to be added to the event queue, just dispatched.") @RpcOptional @RpcDefault("false") Boolean enqueue) {
        postEvent(name, data, enqueue.booleanValue());
    }

    /**
     * Post an event and queue it
     */
    public void postEvent(String name, Object data) {
        postEvent(name, data, true);
    }

    /**
     * Posts an event with to the event queue.
     */
    public void postEvent(String name, Object data, boolean enqueue) {
        Event event = new Event(name, data);
        if (enqueue) {
            Log.v(String.format("postEvent(%s)", name));
            synchronized (mEventQueue) {
                while (mEventQueue.size() >= MAX_QUEUE_SIZE) {
                    mEventQueue.remove();
                }
                mEventQueue.add(event);
                // b/77306870: Posting to the EventObservers when enqueuing an event must be
                // done when mEventQueue is locked. Otherwise, we can run into the following
                // race condition:
                // 1) postEvent() adds the event to the event queue, and releases mEventQueue.
                //                Here, the thread is put to sleep.
                // 2) eventWait() is called when an event is queued, and exits immediately.
                // 3) eventWait() is called a second time, finds no event and creates a
                //                GlobalEventObserver.
                // 4) postEvent() wakes back up, and continues to post the event to the observers.
                //                The same event sent to the first eventWait call is sent to the
                //                second eventWait call's observer, causing a duplicated received
                //                event.
                postEventToNamedObservers(event);
                postEventToGlobalObservers(event);
            }
        } else {
            postEventToNamedObservers(event);
            postEventToGlobalObservers(event);
        }
    }

    /**
     * Posts the event to all applicable Named Observers.
     */
    private void postEventToNamedObservers(Event event) {
        synchronized (mNamedEventObservers) {
            for (EventObserver observer : mNamedEventObservers.get(event.getName())) {
                Log.d(String.format("namedEventObserver %s received event %s",
                        observer,
                        event.getName()));
                observer.onEventReceived(event);
            }
        }
    }

    /**
     * Posts the event to the Global Observers list.
     */
    private void postEventToGlobalObservers(Event event) {
        synchronized (mGlobalEventObservers) {
            for (EventObserver observer : mGlobalEventObservers) {
                Log.d(String.format("globalEventObserver %s received event %s",
                        observer,
                        event.getName()));
                observer.onEventReceived(event);
            }
        }
    }

    @RpcDeprecated(value = "eventPost", release = "r4")
    @Rpc(description = "Post an event to the event queue.")
    @RpcName(name = "postEvent")
    public void rpcPostEvent(
            @RpcParameter(name = "name") String name,
            @RpcParameter(name = "data") String data) {
        postEvent(name, data);
    }

    @RpcDeprecated(value = "eventPoll", release = "r4")
    @Rpc(description = "Returns and removes the oldest event (i.e. location or sensor update, etc.) from the event buffer.",
            returns = "Map of event properties.")
    public Event receiveEvent() {
        return mEventQueue.poll();
    }

    @RpcDeprecated(value = "eventWaitFor", release = "r4")
    @Rpc(description = "Blocks until an event with the supplied name occurs. Event is removed from the buffer if removeEvent is True.",
            returns = "Map of event properties.")
    public Event waitForEvent(
            @RpcParameter(name = "eventName") final String eventName,
            @RpcOptional final Boolean removeEvent,
            @RpcParameter(name = "timeout", description = "the maximum time to wait") @RpcOptional Integer timeout)
            throws InterruptedException {
        return eventWaitFor(eventName, removeEvent, timeout);
    }

    /**
     * Closes this SL4A session, and sends a terminating signal to the event observers.
     */
    @Rpc(description = "sl4a session is shutting down, send terminate event to client.")
    public void closeSl4aSession() {
        eventClearBuffer();
        postEvent("EventDispatcherShutdown", null);
    }

    /**
     * Shuts down the RPC server.
     */
    @Override
    public void shutdown() {
        mGlobalEventObservers.clear();
        mEventQueue.clear();
    }

    /**
     * Adds a named observer to the event listening queue.
     * @param eventName the name of the event to listen to
     * @param observer  the observer object
     */
    public void addNamedEventObserver(String eventName, EventObserver observer) {
        mNamedEventObservers.put(eventName, observer);
    }

    /**
     * Adds a global event listener ot the listening queue.
     * @param observer the observer object
     */
    public void addGlobalEventObserver(EventObserver observer) {
        mGlobalEventObservers.add(observer);
    }

    /**
     * Removes an observer from the event listening queue.
     * @param observer the observer to remove
     */
    public void removeEventObserver(EventObserver observer) {
        mNamedEventObservers.removeAll(observer);
        mGlobalEventObservers.remove(observer);
    }

    public class BroadcastListener extends android.content.BroadcastReceiver {
        private EventFacade mParent;
        private boolean mEnQueue;

        public BroadcastListener(EventFacade parent, boolean enqueue) {
            mParent = parent;
            mEnQueue = enqueue;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle data;
            if (intent.getExtras() != null) {
                data = (Bundle) intent.getExtras().clone();
            } else {
                data = new Bundle();
            }
            data.putString("action", intent.getAction());
            try {
                mParent.eventPost("sl4a", JsonBuilder.build(data).toString(), mEnQueue);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

    }
}
