// Copyright 2015 The Weave 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 "src/commands/command_queue.h"

#include <base/bind.h>
#include <base/time/time.h>

namespace weave {

namespace {
const int kRemoveCommandDelayMin = 5;

std::string GetCommandHandlerKey(const std::string& component_path,
                                 const std::string& command_name) {
  return component_path + ":" + command_name;
}
}

void CommandQueue::AddCommandAddedCallback(const CommandCallback& callback) {
  on_command_added_.push_back(callback);
  // Send all pre-existed commands.
  for (const auto& command : map_)
    callback.Run(command.second.get());
}

void CommandQueue::AddCommandRemovedCallback(const CommandCallback& callback) {
  on_command_removed_.push_back(callback);
}

void CommandQueue::AddCommandHandler(
    const std::string& component_path,
    const std::string& command_name,
    const Device::CommandHandlerCallback& callback) {
  if (!command_name.empty()) {
    CHECK(default_command_callback_.is_null())
        << "Commands specific handler are not allowed after default one";

    for (const auto& command : map_) {
      if (command.second->GetState() == Command::State::kQueued &&
          command.second->GetName() == command_name &&
          command.second->GetComponent() == component_path) {
        callback.Run(command.second);
      }
    }

    std::string key = GetCommandHandlerKey(component_path, command_name);
    CHECK(command_callbacks_.insert(std::make_pair(key, callback)).second)
        << command_name << " already has handler";

  } else {
    CHECK(component_path.empty())
        << "Default handler must not be component-specific";
    for (const auto& command : map_) {
      std::string key = GetCommandHandlerKey(command.second->GetComponent(),
                                             command.second->GetName());
      if (command.second->GetState() == Command::State::kQueued &&
          command_callbacks_.find(key) == command_callbacks_.end()) {
        callback.Run(command.second);
      }
    }

    CHECK(default_command_callback_.is_null()) << "Already has default handler";
    default_command_callback_ = callback;
  }
}

void CommandQueue::Add(std::unique_ptr<CommandInstance> instance) {
  std::string id = instance->GetID();
  LOG_IF(FATAL, id.empty()) << "Command has no ID";
  instance->AttachToQueue(this);
  auto pair = map_.insert(std::make_pair(id, std::move(instance)));
  LOG_IF(FATAL, !pair.second) << "Command with ID '" << id
                              << "' is already in the queue";
  for (const auto& cb : on_command_added_)
    cb.Run(pair.first->second.get());

  std::string key = GetCommandHandlerKey(pair.first->second->GetComponent(),
                                         pair.first->second->GetName());
  auto it_handler = command_callbacks_.find(key);

  if (it_handler != command_callbacks_.end())
    it_handler->second.Run(pair.first->second);
  else if (!default_command_callback_.is_null())
    default_command_callback_.Run(pair.first->second);

  Cleanup();
}

void CommandQueue::DelayedRemove(const std::string& id) {
  auto p = map_.find(id);
  if (p == map_.end())
    return;
  remove_queue_.push(std::make_pair(
      base::Time::Now() + base::TimeDelta::FromMinutes(kRemoveCommandDelayMin),
      id));
  Cleanup();
}

bool CommandQueue::Remove(const std::string& id) {
  auto p = map_.find(id);
  if (p == map_.end())
    return false;
  std::shared_ptr<CommandInstance> instance = p->second;
  instance->DetachFromQueue();
  map_.erase(p);
  for (const auto& cb : on_command_removed_)
    cb.Run(instance.get());
  return true;
}

void CommandQueue::Cleanup() {
  while (!remove_queue_.empty() && remove_queue_.front().first < Now()) {
    Remove(remove_queue_.front().second);
    remove_queue_.pop();
  }
}

void CommandQueue::SetNowForTest(base::Time now) {
  test_now_ = now;
}

base::Time CommandQueue::Now() const {
  return test_now_.is_null() ? base::Time::Now() : test_now_;
}

CommandInstance* CommandQueue::Find(const std::string& id) const {
  auto p = map_.find(id);
  return (p != map_.end()) ? p->second.get() : nullptr;
}

}  // namespace weave
