// Copyright (c) 2020 The Chromium Embedded Framework 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 "libcef/browser/media_router/media_sink_impl.h"

#include "libcef/browser/thread_util.h"

#include "base/strings/string_number_conversions.h"
#include "chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.h"
#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
#include "chrome/common/media_router/discovery/media_sink_internal.h"
#include "chrome/common/media_router/discovery/media_sink_service_base.h"

namespace {

using SinkServiceVector = std::vector<media_router::MediaSinkServiceBase*>;

SinkServiceVector GetSinkServices() {
  CEF_REQUIRE_UIT();
  auto sink_service = media_router::DualMediaSinkService::GetInstance();
  return {sink_service->GetCastMediaSinkServiceImpl(),
          sink_service->GetDialMediaSinkServiceImpl()};
}

void GetSinkInternalAndContinue(
    SinkServiceVector services,
    const media_router::MediaSink::Id& sink_id,
    CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) {
  CEF_REQUIRE_IOT();

  CefMediaSinkDeviceInfo device_info;
  const media_router::MediaSinkInternal* sink_internal = nullptr;

  for (auto service : services) {
    sink_internal = service->GetSinkById(sink_id);
    if (sink_internal)
      break;
  }

  if (sink_internal) {
    if (sink_internal->is_cast_sink()) {
      const auto& cast_data = sink_internal->cast_data();
      CefString(&device_info.ip_address) =
          cast_data.ip_endpoint.ToStringWithoutPort();
      device_info.port = cast_data.ip_endpoint.port();
      CefString(&device_info.model_name) = cast_data.model_name;
    } else if (sink_internal->is_dial_sink()) {
      const auto& dial_data = sink_internal->dial_data();
      CefString(&device_info.ip_address) = dial_data.ip_address.ToString();
      if (dial_data.app_url.is_valid() && dial_data.app_url.has_port()) {
        base::StringToInt(dial_data.app_url.port_piece(), &device_info.port);
      }
      CefString(&device_info.model_name) = dial_data.model_name;
    }
  }

  // Execute the callback on the UI thread.
  CEF_POST_TASK(
      CEF_UIT,
      base::BindOnce(&CefMediaSinkDeviceInfoCallback::OnMediaSinkDeviceInfo,
                     callback, device_info));
}

void GetDeviceInfo(const media_router::MediaSink::Id& sink_id,
                   CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) {
  auto next_step = base::BindOnce(
      [](const media_router::MediaSink::Id& sink_id,
         CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) {
        CEF_POST_TASK(CEF_IOT,
                      base::BindOnce(GetSinkInternalAndContinue,
                                     GetSinkServices(), sink_id, callback));
      },
      sink_id, callback);

  if (CEF_CURRENTLY_ON(CEF_UIT)) {
    std::move(next_step).Run();
  } else {
    CEF_POST_TASK(CEF_UIT, std::move(next_step));
  }
}

}  // namespace

CefMediaSinkImpl::CefMediaSinkImpl(const media_router::MediaSink& sink)
    : sink_(sink) {}

CefMediaSinkImpl::CefMediaSinkImpl(const media_router::MediaSink::Id& sink_id,
                                   const std::string& sink_name)
    : sink_(sink_id, sink_name, media_router::SinkIconType::GENERIC) {}

CefString CefMediaSinkImpl::GetId() {
  return sink_.id();
}

bool CefMediaSinkImpl::IsValid() {
  return true;
}

CefString CefMediaSinkImpl::GetName() {
  return sink_.name();
}

CefString CefMediaSinkImpl::GetDescription() {
  return sink_.description().value_or("");
}

CefMediaSink::IconType CefMediaSinkImpl::GetIconType() {
  // Verify that our enum matches Chromium's values.
  static_assert(static_cast<int>(CEF_MSIT_TOTAL_COUNT) ==
                    static_cast<int>(media_router::SinkIconType::TOTAL_COUNT),
                "enum mismatch");

  return static_cast<CefMediaSink::IconType>(sink_.icon_type());
}

void CefMediaSinkImpl::GetDeviceInfo(
    CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) {
  ::GetDeviceInfo(sink_.id(), callback);
}

bool CefMediaSinkImpl::IsCastSink() {
  return sink_.provider_id() == media_router::CAST;
}

bool CefMediaSinkImpl::IsDialSink() {
  return sink_.provider_id() == media_router::DIAL;
}

bool CefMediaSinkImpl::IsCompatibleWith(CefRefPtr<CefMediaSource> source) {
  if (source) {
    if (IsCastSink())
      return source->IsCastSource();
    if (IsDialSink())
      return source->IsDialSource();
  }
  return false;
}
