// 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);
  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);
    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 && (g_handle_event_callback.Get().is_null() ||
                        !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) {
  g_handle_event_callback.Get() =
      callback ? base::Bind(callback, context) : HandleEventCallback();
}
