// Copyright 2019 The Fuchsia 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 "resume-task.h"

#include <zircon/errors.h>

#include "coordinator.h"

namespace devmgr {

ResumeTask::ResumeTask(fbl::RefPtr<Device> device, uint32_t target_system_state,
                       Completion completion)
    : Task(device->coordinator->dispatcher(), std::move(completion), true),
      device_(std::move(device)),
      target_system_state_(target_system_state) {}

ResumeTask::~ResumeTask(){};

fbl::RefPtr<ResumeTask> ResumeTask::Create(fbl::RefPtr<Device> device, uint32_t target_system_state,
                                           Completion completion) {
  return fbl::MakeRefCounted<ResumeTask>(std::move(device), target_system_state,
                                         std::move(completion));
}

bool ResumeTask::AddParentResumeTask() {
  if (device_->parent() == nullptr) {
    // For a composite device, each component is a parent.
    // Until all the components resume, composite device cannot
    // be resumed.
    if (device_->composite()) {
      bool parent_dependency_added = false;
      for (auto& component : device_->composite()->bound_components()) {
        auto dev = component.bound_device();
        if (dev != nullptr) {
          switch (dev->state()) {
            case Device::State::kDead:
              // One of the parents is dead, we cant resume the device.
              // Complete this task.
              Complete(ZX_ERR_NOT_CONNECTED);
              return false;
            case Device::State::kActive:
            case Device::State::kInitializing:
              continue;
            case Device::State::kUnbinding:
            case Device::State::kSuspending:
            case Device::State::kResuming:
            case Device::State::kResumed:
            case Device::State::kSuspended:
              parent_dependency_added = true;
              AddDependency(dev->RequestResumeTask(target_system_state_));
          }
        }
      }
      if (parent_dependency_added) {
        return true;
      }
    }
    return false;
  }

  switch (device_->parent()->state()) {
    case Device::State::kDead:
      // If parent is dead, we cant resume the device.
      // Complete this task.
      Complete(ZX_ERR_NOT_CONNECTED);
      return false;
    case Device::State::kInitializing:
    case Device::State::kActive:
      return false;
    case Device::State::kUnbinding:
    case Device::State::kSuspending:
    case Device::State::kResuming:
    case Device::State::kResumed:
    case Device::State::kSuspended:
      AddDependency(device_->parent()->RequestResumeTask(target_system_state_));
      return true;
  }
  return false;
}

bool ResumeTask::AddProxyResumeTask() {
  if (device_->flags & DEV_CTX_PROXY) {
    return false;
  }
  if (device_->parent() == nullptr) {
    return false;
  }
  if (device_->parent()->proxy() == nullptr) {
    return false;
  }
  switch (device_->parent()->proxy()->state()) {
    case Device::State::kDead:
      // If parent is dead, we cant resume the device.
      // Complete this task.
      Complete(ZX_ERR_NOT_CONNECTED);
      return false;
    case Device::State::kInitializing:
    case Device::State::kActive:
      return false;
    case Device::State::kUnbinding:
    case Device::State::kSuspending:
    case Device::State::kResuming:
    case Device::State::kResumed:
    case Device::State::kSuspended:
      AddDependency(device_->parent()->proxy()->RequestResumeTask(target_system_state_));
      return true;
  }
  return false;
}

void ResumeTask::Run() {
  switch (device_->state()) {
    case Device::State::kDead:
      return Complete(ZX_ERR_NOT_CONNECTED);
    case Device::State::kActive:
      return Complete(ZX_OK);
    case Device::State::kInitializing: {
      // Currently resume tasks are not scheduled during suspend.
      // Since a device cannot be suspended until init has completed,
      // it does not make sense for a resume task to be running during init.
      ZX_ASSERT(device_->state() != Device::State::kInitializing);
      return;
    }
    case Device::State::kSuspending:
    case Device::State::kUnbinding:
    case Device::State::kSuspended:
    case Device::State::kResumed:
    case Device::State::kResuming:
      break;
  }

  // The device is about to be unbound, wait for it to complete.
  // Eventually we complete when device goes to DEAD
  if (device_->state() == Device::State::kUnbinding) {
    // The remove task depends on the unbind task, so wait for that to complete.
    auto remove_task = device_->GetActiveRemove();
    ZX_ASSERT(remove_task != nullptr);
    AddDependency(remove_task);
    return;
  }

  // The device is about to be suspended, wait for it to complete.
  if (device_->state() == Device::State::kSuspending) {
    auto suspend_task = device_->GetActiveSuspend();
    ZX_ASSERT(suspend_task != nullptr);
    AddDependency(suspend_task);
    return;
  }

  // Handle the device proxy, if it exists, before the parent
  if (AddProxyResumeTask()) {
    return;
  }

  // Add a dependent resume task on parent.
  if (AddParentResumeTask()) {
    return;
  }
  // Check if this device is not in a devhost.  This happens for the
  // top-level devices like /sys provided by devcoordinator,
  // or the device is already dead.
  if (device_->host() == nullptr) {
    // pretend this completed successfully.
    device_->set_state(Device::State::kActive);
    return Complete(ZX_OK);
  }

  auto completion = [this](zx_status_t status) {
    if (status == ZX_OK) {
      device_->set_state(Device::State::kActive);
    } else {
      device_->set_state(Device::State::kSuspended);
    }
    Complete(status);
    return;
  };

  zx_status_t status = device_->SendResume(target_system_state_, std::move(completion));
  if (status != ZX_OK) {
    device_->set_state(Device::State::kSuspended);
    return Complete(status);
  }
}

}  // namespace devmgr
