// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include "starboard/android/shared/application_android.h"

#include <android/looper.h>
#include <android/native_activity.h>
#include <time.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "starboard/accessibility.h"
#include "starboard/android/shared/file_internal.h"
#include "starboard/android/shared/input_events_generator.h"
#include "starboard/android/shared/jni_env_ext.h"
#include "starboard/android/shared/jni_utils.h"
#include "starboard/android/shared/window_internal.h"
#include "starboard/common/condition_variable.h"
#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/string.h"
#include "starboard/event.h"
#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"

namespace starboard {
namespace android {
namespace shared {

namespace {
  enum {
    kLooperIdAndroidCommand,
    kLooperIdAndroidInput,
    kLooperIdKeyboardInject,
  };

  const char* AndroidCommandName(
      ApplicationAndroid::AndroidCommand::CommandType type) {
    switch (type) {
      case ApplicationAndroid::AndroidCommand::kUndefined:
        return "Undefined";
      case ApplicationAndroid::AndroidCommand::kStart:
        return "Start";
      case ApplicationAndroid::AndroidCommand::kResume:
        return "Resume";
      case ApplicationAndroid::AndroidCommand::kPause:
        return "Pause";
      case ApplicationAndroid::AndroidCommand::kStop:
        return "Stop";
      case ApplicationAndroid::AndroidCommand::kInputQueueChanged:
        return "InputQueueChanged";
      case ApplicationAndroid::AndroidCommand::kNativeWindowCreated:
        return "NativeWindowCreated";
      case ApplicationAndroid::AndroidCommand::kNativeWindowDestroyed:
        return "NativeWindowDestroyed";
      case ApplicationAndroid::AndroidCommand::kWindowFocusGained:
        return "WindowFocusGained";
      case ApplicationAndroid::AndroidCommand::kWindowFocusLost:
        return "WindowFocusLost";
      case ApplicationAndroid::AndroidCommand::kDeepLink:
        return "DeepLink";
      default:
        return "unknown";
    }
  }
}  // namespace

// "using" doesn't work with class members, so make a local convenience type.
typedef ::starboard::shared::starboard::Application::Event Event;

ApplicationAndroid::ApplicationAndroid(ALooper* looper)
    : looper_(looper),
      native_window_(NULL),
      input_queue_(NULL),
      android_command_readfd_(-1),
      android_command_writefd_(-1),
      keyboard_inject_readfd_(-1),
      keyboard_inject_writefd_(-1),
      android_command_condition_(android_command_mutex_),
      activity_state_(AndroidCommand::kUndefined),
      window_(kSbWindowInvalid),
      last_is_accessibility_high_contrast_text_enabled_(false) {

  // Initialize Time Zone early so that local time works correctly.
  // Called once here to help SbTimeZoneGet*Name()
  tzset();

  // Initialize Android asset access early so that ICU can load its tables
  // from the assets. The use ICU is used in our logging.
  SbFileAndroidInitialize();

  int pipefd[2];
  int err;

  err = pipe(pipefd);
  SB_CHECK(err >= 0) << "pipe errno is:" << errno;
  android_command_readfd_ = pipefd[0];
  android_command_writefd_ = pipefd[1];
  ALooper_addFd(looper_, android_command_readfd_, kLooperIdAndroidCommand,
                ALOOPER_EVENT_INPUT, NULL, NULL);

  err = pipe(pipefd);
  SB_CHECK(err >= 0) << "pipe errno is:" << errno;
  keyboard_inject_readfd_ = pipefd[0];
  keyboard_inject_writefd_ = pipefd[1];
  ALooper_addFd(looper_, keyboard_inject_readfd_, kLooperIdKeyboardInject,
                ALOOPER_EVENT_INPUT, NULL, NULL);
}

ApplicationAndroid::~ApplicationAndroid() {
  ALooper_removeFd(looper_, android_command_readfd_);
  close(android_command_readfd_);
  close(android_command_writefd_);

  ALooper_removeFd(looper_, keyboard_inject_readfd_);
  close(keyboard_inject_readfd_);
  close(keyboard_inject_writefd_);
}

void ApplicationAndroid::Initialize() {
  SbAudioSinkPrivate::Initialize();
}

void ApplicationAndroid::Teardown() {
  SbAudioSinkPrivate::TearDown();
  SbFileAndroidTeardown();
}

SbWindow ApplicationAndroid::CreateWindow(const SbWindowOptions* options) {
  if (SbWindowIsValid(window_)) {
    return kSbWindowInvalid;
  }
  window_ = new SbWindowPrivate;
  window_->native_window = native_window_;
  input_events_generator_.reset(new InputEventsGenerator(window_));
  return window_;
}

bool ApplicationAndroid::DestroyWindow(SbWindow window) {
  if (!SbWindowIsValid(window)) {
    return false;
  }

  input_events_generator_.reset();

  SB_DCHECK(window == window_);
  delete window_;
  window_ = kSbWindowInvalid;
  return true;
}

Event* ApplicationAndroid::WaitForSystemEventWithTimeout(SbTime time) {
  // Convert from microseconds to milliseconds, taking the ceiling value.
  // If we take the floor, or round, then we end up busy looping every time
  // the next event time is less than one millisecond.
  int timeout_millis = (time + kSbTimeMillisecond - 1) / kSbTimeMillisecond;
  int looper_events;
  int ident = ALooper_pollAll(timeout_millis, NULL, &looper_events, NULL);
  switch (ident) {
    case kLooperIdAndroidCommand:
      ProcessAndroidCommand();
      break;
    case kLooperIdAndroidInput:
      ProcessAndroidInput();
      break;
    case kLooperIdKeyboardInject:
      ProcessKeyboardInject();
      break;
  }

  // Always return NULL since we already dispatched our own system events.
  return NULL;
}

void ApplicationAndroid::WakeSystemEventWait() {
  ALooper_wake(looper_);
}

void ApplicationAndroid::OnResume() {
  JniEnvExt* env = JniEnvExt::Get();
  env->CallStarboardVoidMethodOrAbort("beforeStartOrResume", "()V");
}

void ApplicationAndroid::OnSuspend() {
  JniEnvExt* env = JniEnvExt::Get();
  env->CallStarboardVoidMethodOrAbort("beforeSuspend", "()V");
}

void ApplicationAndroid::StartMediaPlaybackService() {
  JniEnvExt* env = JniEnvExt::Get();
  env->CallStarboardVoidMethodOrAbort("startMediaPlaybackService", "()V");
}

void ApplicationAndroid::StopMediaPlaybackService() {
  JniEnvExt* env = JniEnvExt::Get();
  env->CallStarboardVoidMethodOrAbort("stopMediaPlaybackService", "()V");
}

void ApplicationAndroid::ProcessAndroidCommand() {
  JniEnvExt* env = JniEnvExt::Get();
  AndroidCommand cmd;
  int err = read(android_command_readfd_, &cmd, sizeof(cmd));
  SB_DCHECK(err >= 0) << "Command read failed. errno=" << errno;

  SB_LOG(INFO) << "Android command: " << AndroidCommandName(cmd.type);

  // The activity state to which we should sync the starboard state.
  AndroidCommand::CommandType sync_state = AndroidCommand::kUndefined;

  switch (cmd.type) {
    case AndroidCommand::kUndefined:
      break;

    case AndroidCommand::kInputQueueChanged: {
      ScopedLock lock(android_command_mutex_);
      if (input_queue_) {
        AInputQueue_detachLooper(input_queue_);
      }
      input_queue_ = static_cast<AInputQueue*>(cmd.data);
      if (input_queue_) {
        AInputQueue_attachLooper(input_queue_, looper_, kLooperIdAndroidInput,
                                 NULL, NULL);
      }
      // Now that we've swapped our use of the input queue, signal that the
      // Android UI thread can continue.
      android_command_condition_.Signal();
      break;
    }

    // Starboard resume/suspend is tied to the UI window being created/destroyed
    // (rather than to the Activity lifecycle) since Cobalt can't do anything at
    // all if it doesn't have a window surface to draw on.
    case AndroidCommand::kNativeWindowCreated:
      {
        ScopedLock lock(android_command_mutex_);
        native_window_ = static_cast<ANativeWindow*>(cmd.data);
        if (window_) {
          window_->native_window = native_window_;
        }
        // Media playback service is tied to UI window being created/destroyed
        // (rather than to the Activity lifecycle), the service should be
        // stopped before native window being created.
        StopMediaPlaybackService();
        // Now that we have the window, signal that the Android UI thread can
        // continue, before we start or resume the Starboard app.
        android_command_condition_.Signal();
      }
      if (state() == kStateUnstarted) {
        // This is the initial launch, so we have to start Cobalt now that we
        // have a window.
        env->CallStarboardVoidMethodOrAbort("beforeStartOrResume", "()V");
        DispatchStart();
      } else if (state() == kStateConcealed || state() == kStateFrozen) {
          DispatchAndDelete(new Event(kSbEventTypeReveal, NULL, NULL));
      } else {
        // Now that we got a window back, change the command for the switch
        // below to sync up with the current activity lifecycle.
        sync_state = activity_state_;
      }
      break;
    case AndroidCommand::kNativeWindowDestroyed:
      // No need to JNI call StarboardBridge.beforeSuspend() since we did it
      // early in SendAndroidCommand().
      {
        ScopedLock lock(android_command_mutex_);
        // Media playback service is tied to UI window being created/destroyed
        // (rather than to the Activity lifecycle). The service should be
        // started after window being destroyed.
        StartMediaPlaybackService();
        // Cobalt can't keep running without a window, even if the Activity
        // hasn't stopped yet. DispatchAndDelete() will inject events as needed
        // if we're not already paused.
        DispatchAndDelete(new Event(kSbEventTypeConceal, NULL, NULL));
        if (window_) {
          window_->native_window = NULL;
        }
        native_window_ = NULL;
        // Now that we've suspended the Starboard app, and let go of the window,
        // signal that the Android UI thread can continue.
        android_command_condition_.Signal();
      }
      break;

    case AndroidCommand::kWindowFocusLost:
      break;
    case AndroidCommand::kWindowFocusGained: {
      // Android does not have a publicly-exposed way to
      // register for high-contrast text settings changed events.
      // We assume that it can only change when our focus changes
      // (because the user exits and enters the app) so we check
      // for changes here.
      SbAccessibilityDisplaySettings settings;
      SbMemorySet(&settings, 0, sizeof(settings));
      if (!SbAccessibilityGetDisplaySettings(&settings)) {
        break;
      }

      bool enabled = settings.has_high_contrast_text_setting &&
          settings.is_high_contrast_text_enabled;

      if (enabled != last_is_accessibility_high_contrast_text_enabled_) {
        DispatchAndDelete(new Event(
            kSbEventTypeAccessiblitySettingsChanged, NULL, NULL));
      }
      last_is_accessibility_high_contrast_text_enabled_ = enabled;
      break;
    }

    // Remember the Android activity state to sync to when we have a window.
    case AndroidCommand::kStart:
    case AndroidCommand::kResume:
    case AndroidCommand::kPause:
    case AndroidCommand::kStop:
      sync_state = activity_state_ = cmd.type;
      break;
    case AndroidCommand::kDeepLink:
      char* deep_link = static_cast<char*>(cmd.data);
      SB_LOG(INFO) << "AndroidCommand::kDeepLink: deep_link=" << deep_link
                   << " state=" << state();
      if (deep_link != NULL) {
        if (state() == kStateUnstarted) {
          SetStartLink(deep_link);
          SB_LOG(INFO) << "ApplicationAndroid SetStartLink";
          SbMemoryDeallocate(static_cast<void*>(deep_link));
        } else {
          SB_LOG(INFO) << "ApplicationAndroid Inject: kSbEventTypeLink";
          Inject(new Event(kSbEventTypeLink, deep_link, SbMemoryDeallocate));
        }
      }
      break;
  }

  // If there's a window, sync the app state to the Activity lifecycle, letting
  // DispatchAndDelete() inject events as needed if we missed a state.
  if (native_window_) {
    switch (sync_state) {
      case AndroidCommand::kStart:
        DispatchAndDelete(new Event(kSbEventTypeReveal, NULL, NULL));
        break;
      case AndroidCommand::kResume:
        DispatchAndDelete(new Event(kSbEventTypeFocus, NULL, NULL));
        break;
      case AndroidCommand::kPause:
        DispatchAndDelete(new Event(kSbEventTypeBlur, NULL, NULL));
        break;
      case AndroidCommand::kStop:
        if (state() != kStateConcealed && state() != kStateFrozen) {
          // We usually conceal when losing the window above, but if the window
          // wasn't destroyed (e.g. when Daydream starts) then we still have to
          // conceal when the Activity is stopped.
          DispatchAndDelete(new Event(kSbEventTypeConceal, NULL, NULL));
        }
        break;
      default:
        break;
    }
  }
}

void ApplicationAndroid::SendAndroidCommand(AndroidCommand::CommandType type,
                                            void* data) {
  SB_LOG(INFO) << "Send Android command: " << AndroidCommandName(type);
  AndroidCommand cmd {type, data};
  ScopedLock lock(android_command_mutex_);
  write(android_command_writefd_, &cmd, sizeof(cmd));
  // Synchronization only necessary when managing resources.
  switch (type) {
    case AndroidCommand::kInputQueueChanged:
      while (input_queue_ != data) {
        android_command_condition_.Wait();
      }
      break;
    case AndroidCommand::kNativeWindowCreated:
    case AndroidCommand::kNativeWindowDestroyed:
      while (native_window_ != data) {
        android_command_condition_.Wait();
      }
      break;
    default:
      break;
  }
}

void ApplicationAndroid::ProcessAndroidInput() {
  AInputEvent* android_event = NULL;
  while (AInputQueue_getEvent(input_queue_, &android_event) >= 0) {
    SB_LOG(INFO) << "Android input: type="
                 << AInputEvent_getType(android_event);
    if (AInputQueue_preDispatchEvent(input_queue_, android_event)) {
        continue;
    }
    if (!input_events_generator_) {
      SB_DLOG(WARNING) << "Android input event ignored without an SbWindow.";
      AInputQueue_finishEvent(input_queue_, android_event, false);
      continue;
    }
    InputEventsGenerator::Events app_events;
    bool handled = input_events_generator_->CreateInputEventsFromAndroidEvent(
        android_event, &app_events);
    for (int i = 0; i < app_events.size(); ++i) {
      DispatchAndDelete(app_events[i].release());
    }
    AInputQueue_finishEvent(input_queue_, android_event, handled);
  }
}

void ApplicationAndroid::ProcessKeyboardInject() {
  SbKey key;
  int err = read(keyboard_inject_readfd_, &key, sizeof(key));
  SB_DCHECK(err >= 0) << "Keyboard inject read failed: errno=" << errno;
  SB_LOG(INFO) << "Keyboard inject: " << key;
  if (!input_events_generator_) {
    SB_DLOG(WARNING) << "Injected input event ignored without an SbWindow.";
    return;
  }
  InputEventsGenerator::Events app_events;
  input_events_generator_->CreateInputEventsFromSbKey(key, &app_events);
  for (int i = 0; i < app_events.size(); ++i) {
    DispatchAndDelete(app_events[i].release());
  }
}

void ApplicationAndroid::SendKeyboardInject(SbKey key) {
  write(keyboard_inject_writefd_, &key, sizeof(key));
}

extern "C" SB_EXPORT_PLATFORM void
Java_dev_cobalt_coat_CobaltA11yHelper_nativeInjectKeyEvent(JNIEnv* env,
                                                           jobject unused_clazz,
                                                           jint key) {
  ApplicationAndroid::Get()->SendKeyboardInject(static_cast<SbKey>(key));
}

extern "C" SB_EXPORT_PLATFORM jboolean
Java_dev_cobalt_coat_KeyboardInputConnection_nativeHasOnScreenKeyboard(
    JniEnvExt* env,
    jobject unused_this) {
#if SB_API_VERSION >= 12
  return SbWindowOnScreenKeyboardIsSupported() ? JNI_TRUE : JNI_FALSE;
#elif SB_HAS(ON_SCREEN_KEYBOARD)
  return JNI_TRUE;
#else
  return JNI_FALSE;
#endif
}

#if SB_API_VERSION >= 12 || SB_HAS(ON_SCREEN_KEYBOARD)

void ApplicationAndroid::SbWindowShowOnScreenKeyboard(SbWindow window,
                                                      const char* input_text,
                                                      int ticket) {
  JniEnvExt* env = JniEnvExt::Get();
  jobject j_keyboard_editor = env->CallStarboardObjectMethodOrAbort(
      "getKeyboardEditor", "()Ldev/cobalt/coat/KeyboardEditor;");
  env->CallVoidMethodOrAbort(j_keyboard_editor, "showKeyboard", "()V");
  int* data = new int;
  *data = ticket;
  Inject(new Event(kSbEventTypeOnScreenKeyboardShown, data,
                   &DeleteDestructor<int>));
  return;
}

void ApplicationAndroid::SbWindowHideOnScreenKeyboard(SbWindow window,
                                                      int ticket) {
  JniEnvExt* env = JniEnvExt::Get();
  jobject j_keyboard_editor = env->CallStarboardObjectMethodOrAbort(
      "getKeyboardEditor", "()Ldev/cobalt/coat/KeyboardEditor;");
  env->CallVoidMethodOrAbort(j_keyboard_editor, "hideKeyboard", "()V");
  int* data = new int;
  *data = ticket;
  Inject(new Event(kSbEventTypeOnScreenKeyboardHidden, data,
                   &DeleteDestructor<int>));
  return;
}

void ApplicationAndroid::SbWindowUpdateOnScreenKeyboardSuggestions(
    SbWindow window,
    const std::vector<std::string>& suggestions,
    int ticket) {
  JniEnvExt* env = JniEnvExt::Get();
  jobjectArray completions = env->NewObjectArray(
      suggestions.size(),
      env->FindClass("android/view/inputmethod/CompletionInfo"), 0);
  jstring str;
  jobject j_completion_info;
  for (size_t i = 0; i < suggestions.size(); i++) {
    str = env->NewStringUTF(suggestions[i].c_str());
    j_completion_info =
        env->NewObjectOrAbort("android/view/inputmethod/CompletionInfo",
                              "(JILjava/lang/CharSequence;)V", i, i, str);
    env->SetObjectArrayElement(completions, i, j_completion_info);
  }
  jobject j_keyboard_editor = env->CallStarboardObjectMethodOrAbort(
      "getKeyboardEditor", "()Ldev/cobalt/coat/KeyboardEditor;");
  env->CallVoidMethodOrAbort(j_keyboard_editor, "updateCustomCompletions",
                             "([Landroid/view/inputmethod/CompletionInfo;)V",
                             completions);
  int* data = new int;
  *data = ticket;
  Inject(new Event(kSbEventTypeOnScreenKeyboardSuggestionsUpdated, data,
                   &DeleteDestructor<int>));
  return;
}

extern "C" SB_EXPORT_PLATFORM void
Java_dev_cobalt_coat_KeyboardInputConnection_nativeSendText(
    JniEnvExt* env,
    jobject unused_clazz,
    jstring text,
    jboolean is_composing) {
  if (text) {
    std::string utf_str = env->GetStringStandardUTFOrAbort(text);
    ApplicationAndroid::Get()->SbWindowSendInputEvent(utf_str.c_str(),
                                                      is_composing);
  }
}

void DeleteSbInputDataWithText(void* ptr) {
  SbInputData* data = static_cast<SbInputData*>(ptr);
  const char* input_text = data->input_text;
  data->input_text = NULL;
  delete input_text;
  ApplicationAndroid::DeleteDestructor<SbInputData>(ptr);
}

void ApplicationAndroid::SbWindowSendInputEvent(const char* input_text,
                                                bool is_composing) {
  char* text = SbStringDuplicate(input_text);
  SbInputData* data = new SbInputData();
  SbMemorySet(data, 0, sizeof(*data));
  data->window = window_;
  data->type = kSbInputEventTypeInput;
  data->device_type = kSbInputDeviceTypeOnScreenKeyboard;
  data->input_text = text;
  data->is_composing = is_composing;
  Inject(new Event(kSbEventTypeInput, data, &DeleteSbInputDataWithText));
  return;
}

#endif  // SB_API_VERSION >= 12 ||
        // SB_HAS(ON_SCREEN_KEYBOARD)

bool ApplicationAndroid::OnSearchRequested() {
  for (int i = 0; i < 2; i++) {
    SbInputData* data = new SbInputData();
    SbMemorySet(data, 0, sizeof(*data));
    data->window = window_;
    data->key = kSbKeyBrowserSearch;
    data->type = (i == 0) ? kSbInputEventTypePress : kSbInputEventTypeUnpress;
    Inject(new Event(kSbEventTypeInput, data, &DeleteDestructor<SbInputData>));
  }
  return true;
}

extern "C" SB_EXPORT_PLATFORM
jboolean Java_dev_cobalt_coat_StarboardBridge_nativeOnSearchRequested(
    JniEnvExt* env, jobject unused_this) {
  return ApplicationAndroid::Get()->OnSearchRequested();
}

void ApplicationAndroid::HandleDeepLink(const char* link_url) {
  SB_LOG(INFO) << "ApplicationAndroid::HandleDeepLink link_url=" << link_url;
  if (link_url == NULL || link_url[0] == '\0') {
    return;
  }
  char* deep_link = SbStringDuplicate(link_url);
  SB_DCHECK(deep_link);

  SendAndroidCommand(AndroidCommand::kDeepLink, deep_link);
}

extern "C" SB_EXPORT_PLATFORM
void Java_dev_cobalt_coat_StarboardBridge_nativeHandleDeepLink(
    JniEnvExt* env, jobject unused_this, jstring j_url) {
  if (j_url) {
    std::string utf_str = env->GetStringStandardUTFOrAbort(j_url);
    ApplicationAndroid::Get()->HandleDeepLink(utf_str.c_str());
  }
}

extern "C" SB_EXPORT_PLATFORM
void Java_dev_cobalt_coat_StarboardBridge_nativeStopApp(
    JniEnvExt* env, jobject unused_this, jint error_level) {
  ApplicationAndroid::Get()->Stop(error_level);
}

}  // namespace shared
}  // namespace android
}  // namespace starboard
