// Copyright 2015 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/display/manager/chromeos/query_content_protection_task.h"

#include "ui/display/manager/chromeos/display_layout_manager.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/native_display_delegate.h"

namespace display {

QueryContentProtectionTask::QueryContentProtectionTask(
    DisplayLayoutManager* layout_manager,
    NativeDisplayDelegate* native_display_delegate,
    int64_t display_id,
    const ResponseCallback& callback)
    : layout_manager_(layout_manager),
      native_display_delegate_(native_display_delegate),
      display_id_(display_id),
      callback_(callback),
      pending_requests_(0),
      weak_ptr_factory_(this) {}

QueryContentProtectionTask::~QueryContentProtectionTask() {}

void QueryContentProtectionTask::Run() {
  std::vector<DisplaySnapshot*> hdcp_capable_displays;
  for (DisplaySnapshot* display : layout_manager_->GetDisplayStates()) {
    // Query display if it is in mirror mode or client on the same display.
    if (!layout_manager_->IsMirroring() && display->display_id() != display_id_)
      continue;

    response_.link_mask |= display->type();

    switch (display->type()) {
      case DISPLAY_CONNECTION_TYPE_UNKNOWN:
        callback_.Run(response_);
        return;
      case DISPLAY_CONNECTION_TYPE_DISPLAYPORT:
      case DISPLAY_CONNECTION_TYPE_DVI:
      case DISPLAY_CONNECTION_TYPE_HDMI:
        hdcp_capable_displays.push_back(display);
        break;
      case DISPLAY_CONNECTION_TYPE_INTERNAL:
      case DISPLAY_CONNECTION_TYPE_VGA:
      case DISPLAY_CONNECTION_TYPE_NETWORK:
        // No protections for these types. Do nothing.
        break;
      case DISPLAY_CONNECTION_TYPE_NONE:
        NOTREACHED();
        break;
    }
  }

  response_.success = true;
  pending_requests_ = hdcp_capable_displays.size();
  if (pending_requests_ != 0) {
    for (DisplaySnapshot* display : hdcp_capable_displays) {
      native_display_delegate_->GetHDCPState(
          *display, base::Bind(&QueryContentProtectionTask::OnHDCPStateUpdate,
                               weak_ptr_factory_.GetWeakPtr()));
    }
  } else {
    callback_.Run(response_);
  }
}

void QueryContentProtectionTask::OnHDCPStateUpdate(bool success,
                                                   HDCPState state) {
  response_.success &= success;
  if (state == HDCP_STATE_ENABLED)
    response_.enabled |= CONTENT_PROTECTION_METHOD_HDCP;
  else
    response_.unfulfilled |= CONTENT_PROTECTION_METHOD_HDCP;

  pending_requests_--;
  // Wait for all the requests to finish before invoking the callback.
  if (pending_requests_ != 0)
    return;

  callback_.Run(response_);
}

}  // namespace display
