// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/gtk/unity_service.h"

#include <dlfcn.h>
#include <string>

#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/shell_integration_linux.h"

// Unity data typedefs.
typedef struct _UnityInspector UnityInspector;
typedef UnityInspector* (*unity_inspector_get_default_func)(void);
typedef gboolean (*unity_inspector_get_unity_running_func)
    (UnityInspector* self);

typedef struct _UnityLauncherEntry UnityLauncherEntry;
typedef UnityLauncherEntry* (*unity_launcher_entry_get_for_desktop_id_func)
    (const gchar* desktop_id);
typedef void (*unity_launcher_entry_set_count_func)(UnityLauncherEntry* self,
                                               gint64 value);
typedef void (*unity_launcher_entry_set_count_visible_func)
    (UnityLauncherEntry* self, gboolean value);
typedef void (*unity_launcher_entry_set_progress_func)(UnityLauncherEntry* self,
                                                       gdouble value);
typedef void (*unity_launcher_entry_set_progress_visible_func)
    (UnityLauncherEntry* self, gboolean value);


namespace {

bool attempted_load = false;

// Unity has a singleton object that we can ask whether the unity is running.
UnityInspector* inspector = NULL;

// A link to the desktop entry in the panel.
UnityLauncherEntry* chrome_entry = NULL;

// Retrieved functions from libunity.
unity_inspector_get_unity_running_func get_unity_running = NULL;
unity_launcher_entry_set_count_func entry_set_count = NULL;
unity_launcher_entry_set_count_visible_func entry_set_count_visible = NULL;
unity_launcher_entry_set_progress_func entry_set_progress = NULL;
unity_launcher_entry_set_progress_visible_func entry_set_progress_visible =
    NULL;

void EnsureMethodsLoaded() {
  using base::nix::GetDesktopEnvironment;

  if (attempted_load)
    return;
  attempted_load = true;

  scoped_ptr<base::Environment> env(base::Environment::Create());
  if (GetDesktopEnvironment(env.get()) != base::nix::DESKTOP_ENVIRONMENT_UNITY)
    return;

  // TODO(erg): When unity stabilizes its interface, switch all this to looking
  // up just ".so" instead of specific versions.
  void* unity_lib = dlopen("libunity.so.4", RTLD_LAZY);
  if (!unity_lib)
    unity_lib = dlopen("libunity.so.6", RTLD_LAZY);
  if (!unity_lib)
    unity_lib = dlopen("libunity.so.9", RTLD_LAZY);
  if (!unity_lib)
    return;

  unity_inspector_get_default_func inspector_get_default =
      reinterpret_cast<unity_inspector_get_default_func>(
          dlsym(unity_lib, "unity_inspector_get_default"));
  if (inspector_get_default) {
    inspector = inspector_get_default();

    get_unity_running =
        reinterpret_cast<unity_inspector_get_unity_running_func>(
            dlsym(unity_lib, "unity_inspector_get_unity_running"));
  }

  unity_launcher_entry_get_for_desktop_id_func entry_get_for_desktop_id =
      reinterpret_cast<unity_launcher_entry_get_for_desktop_id_func>(
          dlsym(unity_lib, "unity_launcher_entry_get_for_desktop_id"));
  if (entry_get_for_desktop_id) {
    std::string desktop_id = ShellIntegrationLinux::GetDesktopName(env.get());
    chrome_entry = entry_get_for_desktop_id(desktop_id.c_str());

    entry_set_count =
        reinterpret_cast<unity_launcher_entry_set_count_func>(
            dlsym(unity_lib, "unity_launcher_entry_set_count"));

    entry_set_count_visible =
        reinterpret_cast<unity_launcher_entry_set_count_visible_func>(
            dlsym(unity_lib, "unity_launcher_entry_set_count_visible"));

    entry_set_progress =
        reinterpret_cast<unity_launcher_entry_set_progress_func>(
            dlsym(unity_lib, "unity_launcher_entry_set_progress"));

    entry_set_progress_visible =
        reinterpret_cast<unity_launcher_entry_set_progress_visible_func>(
            dlsym(unity_lib, "unity_launcher_entry_set_progress_visible"));
  }
}

}  // namespace


namespace unity {

bool IsRunning() {
  EnsureMethodsLoaded();
  if (inspector && get_unity_running)
    return get_unity_running(inspector);

  return false;
}

void SetDownloadCount(int count) {
  EnsureMethodsLoaded();
  if (chrome_entry && entry_set_count && entry_set_count_visible) {
    entry_set_count(chrome_entry, count);
    entry_set_count_visible(chrome_entry, count != 0);
  }
}

void SetProgressFraction(float percentage) {
  EnsureMethodsLoaded();
  if (chrome_entry && entry_set_progress && entry_set_progress_visible) {
    entry_set_progress(chrome_entry, percentage);
    entry_set_progress_visible(chrome_entry,
                               percentage > 0.0 && percentage < 1.0);
  }
}

}  // namespace unity
