// 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 "ui/base/accelerators/accelerator_manager.h"

#include <algorithm>

#include "base/logging.h"
#include "base/stl_util.h"

namespace ui {

AcceleratorManager::AcceleratorManager() = default;

AcceleratorManager::~AcceleratorManager() = default;

void AcceleratorManager::Register(
    const std::vector<ui::Accelerator>& accelerators,
    HandlerPriority priority,
    AcceleratorTarget* target) {
  DCHECK(target);

  for (const ui::Accelerator& accelerator : accelerators) {
    AcceleratorTargetList& targets = accelerators_[accelerator].second;
    DCHECK(!base::ContainsValue(targets, target))
        << "Registering the same target multiple times";

    // All priority accelerators go to the front of the line.
    if (priority == kHighPriority) {
      DCHECK(!accelerators_[accelerator].first)
          << "Only one high-priority handler can be registered";
      targets.push_front(target);
      // Mark that we have a priority accelerator at the front.
      accelerators_[accelerator].first = true;
    } else {
      // We are registering a normal priority handler. If no priority
      // accelerator handler has been registered before us, just add the new
      // handler to the front. Otherwise, register it after the first (only)
      // priority handler.
      if (!accelerators_[accelerator].first)
        targets.push_front(target);
      else
        targets.insert(++targets.begin(), target);
    }
  }
}

void AcceleratorManager::Unregister(const Accelerator& accelerator,
                                    AcceleratorTarget* target) {
  auto map_iter = accelerators_.find(accelerator);
  if (map_iter == accelerators_.end()) {
    NOTREACHED() << "Unregistering non-existing accelerator";
    return;
  }

  UnregisterImpl(map_iter, target);
}

void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
  for (auto map_iter = accelerators_.begin();
       map_iter != accelerators_.end();) {
    AcceleratorTargetList* targets = &map_iter->second.second;
    if (!base::ContainsValue(*targets, target)) {
      ++map_iter;
    } else {
      auto tmp_iter = map_iter;
      ++map_iter;
      UnregisterImpl(tmp_iter, target);
    }
  }
}

bool AcceleratorManager::IsRegistered(const Accelerator& accelerator) const {
  auto map_iter = accelerators_.find(accelerator);
  return map_iter != accelerators_.end() && !map_iter->second.second.empty();
}

bool AcceleratorManager::Process(const Accelerator& accelerator) {
  auto map_iter = accelerators_.find(accelerator);
  if (map_iter == accelerators_.end())
    return false;

  // We have to copy the target list here, because an AcceleratorPressed
  // event handler may modify the list.
  AcceleratorTargetList targets(map_iter->second.second);
  for (auto iter = targets.begin(); iter != targets.end(); ++iter) {
    if ((*iter)->CanHandleAccelerators() &&
        (*iter)->AcceleratorPressed(accelerator)) {
      return true;
    }
  }

  return false;
}

bool AcceleratorManager::HasPriorityHandler(
    const Accelerator& accelerator) const {
  auto map_iter = accelerators_.find(accelerator);
  if (map_iter == accelerators_.end() || map_iter->second.second.empty())
    return false;

  // Check if we have a priority handler. If not, there's no more work needed.
  if (!map_iter->second.first)
    return false;

  // If the priority handler says it cannot handle the accelerator, we must not
  // count it as one.
  return map_iter->second.second.front()->CanHandleAccelerators();
}

void AcceleratorManager::UnregisterImpl(AcceleratorMap::iterator map_iter,
                                        AcceleratorTarget* target) {
  AcceleratorTargetList* targets = &map_iter->second.second;
  auto target_iter = std::find(targets->begin(), targets->end(), target);
  if (target_iter == targets->end()) {
    NOTREACHED() << "Unregistering accelerator for wrong target";
    return;
  }

  // Only one priority handler is allowed, so if we remove the first element we
  // no longer have a priority target.
  if (target_iter == targets->begin())
    map_iter->second.first = false;

  targets->remove(target);
  if (!targets->empty())
    return;
  accelerators_.erase(map_iter);
}

}  // namespace ui
