// Copyright (c) 2013 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/extensions/global_shortcut_listener.h"

#include "base/logging.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/accelerators/accelerator.h"

using content::BrowserThread;

namespace extensions {

GlobalShortcutListener::GlobalShortcutListener()
    : shortcut_handling_suspended_(false) {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

GlobalShortcutListener::~GlobalShortcutListener() {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(accelerator_map_.empty());  // Make sure we've cleaned up.
}

bool GlobalShortcutListener::RegisterAccelerator(
    const ui::Accelerator& accelerator, Observer* observer) {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (IsShortcutHandlingSuspended())
    return false;

  AcceleratorMap::const_iterator it = accelerator_map_.find(accelerator);
  if (it != accelerator_map_.end()) {
    // The accelerator has been registered.
    return false;
  }

  if (!RegisterAcceleratorImpl(accelerator)) {
    // If the platform-specific registration fails, mostly likely the shortcut
    // has been registered by other native applications.
    return false;
  }

  if (accelerator_map_.empty())
    StartListening();

  accelerator_map_[accelerator] = observer;
  return true;
}

void GlobalShortcutListener::UnregisterAccelerator(
    const ui::Accelerator& accelerator, Observer* observer) {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (IsShortcutHandlingSuspended())
    return;

  auto it = accelerator_map_.find(accelerator);
  // We should never get asked to unregister something that we didn't register.
  DCHECK(it != accelerator_map_.end());
  // The caller should call this function with the right observer.
  DCHECK(it->second == observer);

  UnregisterAcceleratorImpl(accelerator);
  accelerator_map_.erase(it);
  if (accelerator_map_.empty())
    StopListening();
}

void GlobalShortcutListener::UnregisterAccelerators(Observer* observer) {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (IsShortcutHandlingSuspended())
    return;

  auto it = accelerator_map_.begin();
  while (it != accelerator_map_.end()) {
    if (it->second == observer) {
      auto to_remove = it++;
      UnregisterAccelerator(to_remove->first, observer);
    } else {
      ++it;
    }
  }
}

void GlobalShortcutListener::SetShortcutHandlingSuspended(bool suspended) {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (shortcut_handling_suspended_ == suspended)
    return;

  shortcut_handling_suspended_ = suspended;
  for (auto it = accelerator_map_.begin(); it != accelerator_map_.end(); ++it) {
    // On Linux, when shortcut handling is suspended we cannot simply early
    // return in NotifyKeyPressed (similar to what we do for non-global
    // shortcuts) because we'd eat the keyboard event thereby preventing the
    // user from setting the shortcut. Therefore we must unregister while
    // handling is suspended and register when handling resumes.
    if (shortcut_handling_suspended_)
      UnregisterAcceleratorImpl(it->first);
    else
      RegisterAcceleratorImpl(it->first);
  }
}

bool GlobalShortcutListener::IsShortcutHandlingSuspended() const {
  return shortcut_handling_suspended_;
}

void GlobalShortcutListener::NotifyKeyPressed(
    const ui::Accelerator& accelerator) {
  auto iter = accelerator_map_.find(accelerator);
  if (iter == accelerator_map_.end()) {
    // This should never occur, because if it does, we have failed to unregister
    // or failed to clean up the map after unregistering the shortcut.
    NOTREACHED();
    return;  // No-one is listening to this key.
  }

  iter->second->OnKeyPressed(accelerator);
}

}  // namespace extensions
