#include "media/preview_conversion.hpp"

#ifdef SMARTCUT_HAS_FFMPEG
extern "C" {
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
#endif

namespace smartcut::media {

std::shared_ptr<core::PreviewFrame> convert_preview_to_bgra(
    const std::shared_ptr<core::PreviewFrame>& source,
    int output_width, int output_height) {
  if (!source) return {};
#ifndef SMARTCUT_HAS_FFMPEG
  (void)output_width;
  (void)output_height;
  return {};
#else
  auto output = std::make_shared<core::PreviewFrame>(*source);
  output_width = output_width > 0 ? output_width : source->width;
  output_height = output_height > 0 ? output_height : source->height;
  output->display_color_mode = "source-bgra";
  output->tone_mapped = false;
  output->pixel_format = AV_PIX_FMT_BGRA;
  output->width = output_width; output->height = output_height;
  output->stride = output_width * 4;
  output->pixels.resize(static_cast<std::size_t>(output->stride) * static_cast<std::size_t>(output_height));
  std::uint8_t* source_data[4]{};
  int source_linesize[4]{};
  if (av_image_fill_arrays(source_data, source_linesize, source->pixels.data(), static_cast<AVPixelFormat>(source->pixel_format), source->width, source->height, 1) < 0) return {};
  std::uint8_t* output_data[4]{output->pixels.data(), nullptr, nullptr, nullptr};
  int output_linesize[4]{output->stride, 0, 0, 0};
  SwsContext* scaler = sws_getContext(source->width, source->height, static_cast<AVPixelFormat>(source->pixel_format), output_width, output_height, AV_PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, nullptr);
  if (!scaler) return {};
  const int scaled = sws_scale(scaler, source_data, source_linesize, 0, source->height, output_data, output_linesize);
  sws_freeContext(scaler);
  return scaled == output_height ? output : nullptr;
#endif
}

std::shared_ptr<core::PreviewFrame> tone_map_bgra_sdr(const std::shared_ptr<core::PreviewFrame>& source) {
  if (!source || source->pixel_format != 28 || source->pixels.size() < static_cast<std::size_t>(source->stride) * static_cast<std::size_t>(source->height)) return {};
  auto output = std::make_shared<core::PreviewFrame>(*source);
  output->display_color_mode = "tone-mapped-sdr";
  output->tone_mapped = true;
  for (std::size_t i = 0; i + 3 < output->pixels.size(); i += 4) {
    for (int channel = 0; channel < 3; ++channel) {
      const unsigned value = output->pixels[i + static_cast<std::size_t>(channel)];
      output->pixels[i + static_cast<std::size_t>(channel)] = static_cast<std::uint8_t>((value * 255U) / (value + 128U));
    }
  }
  return output;
}

}  // namespace smartcut::media
