// Copyright 2017 Google Inc. 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 "cobalt/browser/lib/exported/main.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "cobalt/base/wrap_main.h"
#include "cobalt/browser/application.h"
#include "starboard/event.h"
#include "starboard/input.h"

namespace {

cobalt::browser::Application* g_application = NULL;
typedef base::Callback<void(void)> InitializedCallback;
typedef base::Callback<bool(const SbEvent*)> HandleEventCallback;
static base::LazyInstance<InitializedCallback>
    g_on_cobalt_initialized_callback = LAZY_INSTANCE_INITIALIZER;
static base::LazyInstance<HandleEventCallback> g_handle_event_callback =
    LAZY_INSTANCE_INITIALIZER;

// We cannot use LazyInstance here as this can be set before Cobalt has been
// initialized at all - thus there will not yet exist an AtExitManager which
// means the app would crash if we tried to replace the lazy instance too
// early. Instead, for this one callback, we simply do things manually.
CbLibMainCallbackRegistrationReadyCallback g_callback_registration_ready =
    nullptr;
void* g_registration_ready_context = nullptr;

void PreloadApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
                        const base::Closure& quit_closure) {
  LOG(INFO) << "Preloading application.";
  DCHECK(!g_application);
  CHECK(g_callback_registration_ready);
  // Register a default event handler up front.
  CbLibMainSetHandleEventCallback(nullptr, nullptr);
  g_callback_registration_ready(g_registration_ready_context);
  g_application =
      new cobalt::browser::Application(quit_closure, true /*should_preload*/);
  DCHECK(g_application);
}

void StartApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
                      const base::Closure& quit_closure) {
  LOG(INFO) << "Starting application.";
  if (!g_application) {
    CHECK(g_callback_registration_ready);
    // Register a default event handler up front.
    CbLibMainSetHandleEventCallback(nullptr, nullptr);
    g_callback_registration_ready(g_registration_ready_context);
    g_application = new cobalt::browser::Application(quit_closure,
                                                     false /*should_preload*/);
    DCHECK(g_application);
  } else {
    g_application->Start();
  }
  DCHECK(g_application);
  if (!g_on_cobalt_initialized_callback.Get().is_null())
    g_on_cobalt_initialized_callback.Get().Run();
}

void StopApplication() {
  DCHECK(g_application);
  LOG(INFO) << "Stopping application.";
  delete g_application;
  g_application = NULL;
}

void HandleStarboardEvent(const SbEvent* starboard_event) {
  if (!g_application) {
    return;
  }

  // TODO(dworsham): Host-generated input events will also be fed through the
  // host callback, leading to re-entrancy issues.  Set up a way of filtering
  // them somehow.
  //
  // For now, works fine with YTVR as only input events are generated by the
  // host and the host also ignores all input events sent its way.
  if (!g_handle_event_callback.Get().Run(starboard_event)) {
    g_application->HandleStarboardEvent(starboard_event);
  }
}

}  // namespace

COBALT_WRAP_MAIN(PreloadApplication, StartApplication, HandleStarboardEvent,
                 StopApplication);

void CbLibMainSetCallbackRegistrationReadyCallback(
    void* context, CbLibMainOnCobaltInitializedCallback callback) {
  g_registration_ready_context = context;
  g_callback_registration_ready = callback;
}

void CbLibMainSetOnCobaltInitializedCallback(
    void* context, CbLibMainOnCobaltInitializedCallback callback) {
  g_on_cobalt_initialized_callback.Get() =
      callback ? base::Bind(callback, context) : InitializedCallback();
}

void CbLibMainSetHandleEventCallback(void* context,
                                     CbLibMainHandleEventCallback callback) {
  // If the user passes nullptr, provide a default event handler so that it is
  // never actually null.
  g_handle_event_callback.Get() = callback ?
      base::Bind(callback, context) :
      base::Bind([](const SbEvent*) {
        return false;
      });
}

SbWindow CbLibMainGetSbWindow() {
  auto* primary_window = cobalt::system_window::SystemWindow::PrimaryWindow();
  return primary_window ? primary_window->GetSbWindow() : nullptr;
}
