// 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"

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 fragment is a parent.
    // Until all the fragments resume, composite device cannot
    // be resumed.
    if (device_->composite()) {
      bool parent_dependency_added = false;
      for (auto& fragment : device_->composite()->bound_fragments()) {
        auto dev = fragment.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 driver_host.  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);
  }
}
