// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "embedders/openglui/android/eventloop.h"

#include "embedders/openglui/common/log.h"

EventLoop::EventLoop(android_app* application)
    : enabled_(false),
      quit_(false),
      application_(application),
      lifecycle_handler_(NULL),
      input_handler_(NULL) {
  application_->onAppCmd = ActivityCallback;
  application_->onInputEvent = InputCallback;
  application_->userData = this;
}

void EventLoop::Run(LifeCycleHandler* lifecycle_handler,
                    InputHandler* input_handler) {
  int32_t result;
  int32_t events;
  android_poll_source* source;

  lifecycle_handler_ = lifecycle_handler;
  input_handler_ = input_handler;
  LOGI("Starting event loop");
  while (true) {
    // If not enabled, block indefinitely on events. If enabled, block
    // briefly so we can do useful work in onStep. Ultimately this is
    // where we would want to look at elapsed time since the last call
    // to onStep completed and use a delay that gives us ~60fps.
    while ((result = ALooper_pollAll(enabled_ ? (1000/60) : -1,
                                     NULL,
                                     &events,
                                     reinterpret_cast<void**>(&source))) >= 0) {
      if (source != NULL) {
        source->process(application_, source);
      }
      if (application_->destroyRequested) {
        return;
      }
    }
    if (enabled_ && !quit_) {
      LOGI("step");
      if (lifecycle_handler_->OnStep() != 0) {
        quit_ = true;
        ANativeActivity_finish(application_->activity);
      }
    }
  }
}

// Called when we gain focus.
void EventLoop::Activate() {
  LOGI("activate");
  if (!enabled_ && application_->window != NULL) {
    quit_ = false;
    enabled_ = true;
    if (lifecycle_handler_->OnActivate() != 0) {
      quit_ = true;
      ANativeActivity_finish(application_->activity);
    }
  }
}

// Called when we lose focus.
void EventLoop::Deactivate() {
  LOGI("deactivate");
  if (enabled_) {
    lifecycle_handler_->OnDeactivate();
    enabled_ = false;
  }
}

void EventLoop::ProcessActivityEvent(int32_t command) {
  switch (command) {
    case APP_CMD_CONFIG_CHANGED:
      lifecycle_handler_->OnConfigurationChanged();
      break;
    case APP_CMD_INIT_WINDOW:
      lifecycle_handler_->OnCreateWindow();
      break;
    case APP_CMD_DESTROY:
      lifecycle_handler_->OnDestroy();
      break;
    case APP_CMD_GAINED_FOCUS:
      Activate();
      lifecycle_handler_->OnGainedFocus();
      break;
    case APP_CMD_LOST_FOCUS:
      lifecycle_handler_->OnLostFocus();
      Deactivate();
      break;
    case APP_CMD_LOW_MEMORY:
      lifecycle_handler_->OnLowMemory();
      break;
    case APP_CMD_PAUSE:
      lifecycle_handler_->OnPause();
      Deactivate();
      break;
    case APP_CMD_RESUME:
      lifecycle_handler_->OnResume();
      break;
    case APP_CMD_SAVE_STATE:
      lifecycle_handler_->OnSaveState(&application_->savedState,
                                    &application_->savedStateSize);
      break;
    case APP_CMD_START:
      lifecycle_handler_->OnStart();
      break;
    case APP_CMD_STOP:
      lifecycle_handler_->OnStop();
      break;
    case APP_CMD_TERM_WINDOW:
      lifecycle_handler_->OnDestroyWindow();
      Deactivate();
      break;
    default:
      break;
  }
}

bool EventLoop::OnTouchEvent(AInputEvent* event) {
  int32_t type = AMotionEvent_getAction(event);
  MotionEvent motion_event;
  switch (type) {
    case AMOTION_EVENT_ACTION_DOWN:
      motion_event = kMotionDown;
      break;
    case AMOTION_EVENT_ACTION_UP:
      motion_event = kMotionUp;
      break;
    case AMOTION_EVENT_ACTION_MOVE:
      motion_event = kMotionMove;
      break;
    case AMOTION_EVENT_ACTION_CANCEL:
      motion_event = kMotionCancel;
      break;
    case AMOTION_EVENT_ACTION_OUTSIDE:
      motion_event = kMotionOutside;
      break;
    case AMOTION_EVENT_ACTION_POINTER_DOWN:
      motion_event = kMotionPointerDown;
      break;
    case AMOTION_EVENT_ACTION_POINTER_UP:
      motion_event = kMotionPointerUp;
      break;
    default:
      return false;
  }
  // For now we just get the last coords.
  float move_x = AMotionEvent_getX(event, 0);
  float move_y = AMotionEvent_getY(event, 0);
  int64_t when = AMotionEvent_getEventTime(event);
  LOGI("Got motion event %d at %f, %f", type, move_x, move_y);

  if (input_handler_->OnMotionEvent(motion_event, when, move_x, move_y) != 0) {
    return false;
  }
  return true;
}

bool EventLoop::OnKeyEvent(AInputEvent* event) {
  int32_t type = AKeyEvent_getAction(event);
  KeyEvent key_event;
  switch (type) {
    case AKEY_EVENT_ACTION_DOWN:
      key_event = kKeyDown;
      break;
    case AKEY_EVENT_ACTION_UP:
      key_event = kKeyUp;
      break;
    case AKEY_EVENT_ACTION_MULTIPLE:
      key_event = kKeyMultiple;
      break;
    default:
      return false;
  }
  int32_t flags = AKeyEvent_getFlags(event);
  /* Get the key code of the key event.
   * This is the physical key that was pressed, not the Unicode character. */
  int32_t key_code = AKeyEvent_getKeyCode(event);
  /* Get the meta key state. */
  int32_t meta_state = AKeyEvent_getMetaState(event);
  /* Get the repeat count of the event.
   * For both key up an key down events, this is the number of times the key
   * has repeated with the first down starting at 0 and counting up from
   * there.  For multiple key events, this is the number of down/up pairs
   * that have occurred. */
  int32_t repeat = AKeyEvent_getRepeatCount(event);

  /* Get the time of the most recent key down event, in the	
   * java.lang.System.nanoTime() time base.  If this is a down event,	
   * this will be the same as eventTime.	
   * Note that when chording keys, this value is the down time of the most	
   * recently pressed key, which may not be the same physical key of this	
   * event. */	
  // TODO(gram): Use or remove this.
  // int64_t key_down_time = AKeyEvent_getDownTime(event);

  /* Get the time this event occurred, in the
   * java.lang.System.nanoTime() time base. */
  int64_t when = AKeyEvent_getEventTime(event);

  LOGI("Got key event %d %d", type, key_code);
  if (input_handler_->OnKeyEvent(key_event, when, flags, key_code,
                             meta_state, repeat) != 0) {
    return false;
  }
  return true;
}

int32_t EventLoop::ProcessInputEvent(AInputEvent* event) {
  int32_t event_type = AInputEvent_getType(event);
  LOGI("Got input event type %d", event_type);
  switch (event_type) {
    case AINPUT_EVENT_TYPE_MOTION:
      if (AInputEvent_getSource(event) == AINPUT_SOURCE_TOUCHSCREEN) {
          return OnTouchEvent(event);
      }
      break;
    case AINPUT_EVENT_TYPE_KEY:
      return OnKeyEvent(event);
  }
  return 0;
}

void EventLoop::ActivityCallback(android_app* application, int32_t command) {
  EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
  event_loop->ProcessActivityEvent(command);
}

int32_t EventLoop::InputCallback(android_app* application,
                                 AInputEvent* event) {
  EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
  return event_loop->ProcessInputEvent(event);
}

