// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/api/indigo_private/indigo_private_api.h"

#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/notreached.h"
#include "chrome/browser/indigo/indigo_image_replacement.h"
#include "chrome/browser/indigo/indigo_image_replacement_manager.h"
#include "chrome/common/extensions/api/indigo_private.h"
#include "content/public/browser/render_frame_host.h"

namespace extensions {

namespace {
indigo::IndigoImageReplacement* GetImageReplacement(
    content::RenderFrameHost* rfh) {
  if (!rfh) {
    return nullptr;
  }

  content::Page& page = rfh->GetPage();
  indigo::IndigoImageReplacementManager* manager =
      indigo::IndigoImageReplacementManager::GetForPage(page);
  if (!manager) {
    return nullptr;
  }

  return manager->GetImageReplacementForFrame(*rfh);
}

api::indigo_private::ObjectFit ConvertObjectFitToApi(
    blink::mojom::ObjectFit object_fit) {
  switch (object_fit) {
    case blink::mojom::ObjectFit::kFill:
      return api::indigo_private::ObjectFit::kFill;
    case blink::mojom::ObjectFit::kContain:
      return api::indigo_private::ObjectFit::kContain;
    case blink::mojom::ObjectFit::kCover:
      return api::indigo_private::ObjectFit::kCover;
    case blink::mojom::ObjectFit::kScaleDown:
      return api::indigo_private::ObjectFit::kScaleDown;
    case blink::mojom::ObjectFit::kNone:
      return api::indigo_private::ObjectFit::kObjectFitNone;
  }
  NOTREACHED();
}
}  // namespace

IndigoPrivateReadyToRenderFunction::IndigoPrivateReadyToRenderFunction() =
    default;

IndigoPrivateReadyToRenderFunction::~IndigoPrivateReadyToRenderFunction() =
    default;

ExtensionFunction::ResponseAction IndigoPrivateReadyToRenderFunction::Run() {
  indigo::IndigoImageReplacement* replacement =
      GetImageReplacement(render_frame_host());
  if (!replacement) {
    return RespondNow(Error("No image replacement found"));
  }

  int32_t invocation_id = replacement->OnReadyToRender();
  return RespondNow(WithArguments(invocation_id));
}

IndigoPrivateGetOriginalImageFunction::IndigoPrivateGetOriginalImageFunction() =
    default;

IndigoPrivateGetOriginalImageFunction::
    ~IndigoPrivateGetOriginalImageFunction() = default;

ExtensionFunction::ResponseAction IndigoPrivateGetOriginalImageFunction::Run() {
  indigo::IndigoImageReplacement* replacement =
      GetImageReplacement(render_frame_host());
  if (!replacement) {
    return RespondNow(Error("No image replacement found"));
  }

  std::vector<uint8_t> image_bytes = replacement->TakeOriginalImageWebpBytes();
  if (image_bytes.empty()) {
    return RespondNow(Error("Original image not available"));
  }

  api::indigo_private::ImageData result;
  api::indigo_private::ImageData::Value value;
  value.as_binary = std::move(image_bytes);
  result.value = std::move(value);

  auto object_fit = ConvertObjectFitToApi(replacement->object_fit());
  CHECK_NE(object_fit, api::indigo_private::ObjectFit::kNone);
  result.object_fit = object_fit;

  return RespondNow(ArgumentList(
      api::indigo_private::GetOriginalImage::Results::Create(result)));
}

IndigoPrivateGetReplacementImageFunction::
    IndigoPrivateGetReplacementImageFunction() = default;

IndigoPrivateGetReplacementImageFunction::
    ~IndigoPrivateGetReplacementImageFunction() = default;

ExtensionFunction::ResponseAction
IndigoPrivateGetReplacementImageFunction::Run() {
  indigo::IndigoImageReplacement* replacement =
      GetImageReplacement(render_frame_host());
  if (!replacement) {
    return RespondNow(Error("No image replacement found"));
  }

  const GURL& url = replacement->GetReplacementImageURL();
  if (!url.is_empty()) {
    api::indigo_private::ImageData result;
    api::indigo_private::ImageData::Value value;
    value.as_string = url.spec();
    result.value = std::move(value);
    return RespondNow(ArgumentList(
        api::indigo_private::GetReplacementImage::Results::Create(result)));
  }

  if (!replacement->SetPendingReplacementImageCallback(
          base::BindOnce(&IndigoPrivateGetReplacementImageFunction::
                             OnReplacementImageAvailable,
                         this))) {
    return RespondNow(Error("Already waiting for replacement image"));
  }
  return RespondLater();
}

void IndigoPrivateGetReplacementImageFunction::OnReplacementImageAvailable(
    const GURL& replacement_image_url) {
  if (!browser_context()) {
    return;
  }
  if (replacement_image_url.is_empty()) {
    Respond(Error("Image replacement cancelled"));
    return;
  }
  api::indigo_private::ImageData result;
  api::indigo_private::ImageData::Value value;
  value.as_string = replacement_image_url.spec();
  result.value = std::move(value);
  Respond(ArgumentList(
      api::indigo_private::GetReplacementImage::Results::Create(result)));
}

}  // namespace extensions
