/*
 * Copyright (C) 2010 Google Inc.
 *
 * 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.event.Event;
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 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;

import org.json.JSONException;

/**
 * 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.
 * 
 * @author Felix Arends (felix.arends@gmail.com)
 * 
 */
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 EventServer mEventServer = null;
  private final HashMap<String, BroadcastListener> mBroadcastListeners =
      new HashMap<String, BroadcastListener>();
  private final Context mContext;

  public EventFacade(FacadeManager manager) {
    super(manager);
    mContext = manager.getService().getApplicationContext();
  }

  /**
   * 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.
   * 
   * <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>
   * 
   * 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;
    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;
        }
      }
    }
    final FutureResult<Event> 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);
              removeEventObserver(this);
            }
            if(removeEvent)
              mEventQueue.remove(event);
          }
        }
      }
    });
    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>();
    synchronized (mEventQueue) { // Anything in queue?
      if (mEventQueue.size() > 0) {
        return mEventQueue.poll(); // return it.
      }
    }
    EventObserver observer = new EventObserver() {
      @Override
      public void onEventReceived(Event event) { // set up observer for any events.
        synchronized (futureEvent) {
          if (!futureEvent.isDone()) {
            futureEvent.set(event);
            removeEventObserver(this);
          }
          mEventQueue.remove(event);
        }
      }
    };
    addGlobalEventObserver(observer);
    if (timeout != null) {
      result = futureEvent.get(timeout, TimeUnit.MILLISECONDS);
    } else {
      result = futureEvent.get();
    }
    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 != false) {
      mEventQueue.add(event);
      if (mEventQueue.size() > MAX_QUEUE_SIZE) {
        mEventQueue.remove();
      }
    }
    synchronized (mNamedEventObservers) {
      for (EventObserver observer : mNamedEventObservers.get(name)) {
        observer.onEventReceived(event);
      }
    }
    synchronized (mGlobalEventObservers) {
      for (EventObserver observer : mGlobalEventObservers) {
        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);
  }

  @Rpc(description = "Opens up a socket where you can read for events posted")
  public int startEventDispatcher(
      @RpcParameter(name = "port", description = "Port to use") @RpcDefault("0") @RpcOptional() Integer port) {
    if (mEventServer == null) {
      if (port == null) {
        port = 0;
      }
      mEventServer = new EventServer(port);
      addGlobalEventObserver(mEventServer);
    }
    return mEventServer.getAddress().getPort();
  }

  @Rpc(description = "Stops the event server, you can't read in the port anymore")
  public void stopEventDispatcher() throws RuntimeException {
    if (mEventServer == null) {
      throw new RuntimeException("Not running");
    }
    mEventServer.shutdown();
    removeEventObserver(mEventServer);
    mEventServer = null;
    return;
  }

  @Override
  public void shutdown() {
    try {
      stopEventDispatcher();
    } catch (Exception err) {
    }
    // let others (like webviews) know we're going down
    postEvent("sl4a", "{\"shutdown\": \"event-facade\"}");
  }

  public void addNamedEventObserver(String eventName, EventObserver observer) {
    mNamedEventObservers.put(eventName, observer);
  }

  public void addGlobalEventObserver(EventObserver observer) {
    mGlobalEventObservers.add(observer);
  }

  public void removeEventObserver(EventObserver observer) {
    mNamedEventObservers.removeAll(observer);
    mGlobalEventObservers.remove(observer);
  }

  public interface EventObserver {
    public void onEventReceived(Event event);
  }

  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();
      }
    }

  }
}
