// Copyright 2013 The Flutter 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 <iostream>

#include "flutter/lib/ui/painting/fragment_shader.h"

#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/fragment_program.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/typed_data/typed_list.h"

namespace flutter {

// Since _FragmentShader is a private class, we can't use
// IMPLEMENT_WRAPPERTYPEINFO
static const tonic::DartWrapperInfo kDartWrapperInfo_ui_FragmentShader = {
    "ui",
    "_FragmentShader",
};
const tonic::DartWrapperInfo& FragmentShader::dart_wrapper_info_ =
    kDartWrapperInfo_ui_FragmentShader;

std::shared_ptr<DlColorSource> FragmentShader::shader(
    DlImageSampling sampling) {
  // Sampling options are ignored, since sampling options don't make sense for
  // generative shaders.
  return source_;
}

fml::RefPtr<FragmentShader> FragmentShader::Create(
    Dart_Handle dart_handle,
    std::shared_ptr<DlRuntimeEffectColorSource> shader) {
  auto fragment_shader = fml::MakeRefCounted<FragmentShader>(std::move(shader));
  fragment_shader->AssociateWithDartWrapper(dart_handle);
  return fragment_shader;
}

FragmentShader::FragmentShader(
    std::shared_ptr<DlRuntimeEffectColorSource> shader)
    : source_(std::move(shader)) {}

FragmentShader::~FragmentShader() = default;

IMPLEMENT_WRAPPERTYPEINFO(ui, ReusableFragmentShader);

ReusableFragmentShader::ReusableFragmentShader(
    fml::RefPtr<FragmentProgram> program,
    uint64_t float_count,
    uint64_t sampler_count)
    : program_(program),
      uniform_data_(SkData::MakeUninitialized(
          (float_count + 2 * sampler_count) * sizeof(float))),
      samplers_(sampler_count),
      float_count_(float_count) {}

Dart_Handle ReusableFragmentShader::Create(Dart_Handle wrapper,
                                           Dart_Handle program,
                                           Dart_Handle float_count_handle,
                                           Dart_Handle sampler_count_handle) {
  auto* fragment_program =
      tonic::DartConverter<FragmentProgram*>::FromDart(program);
  uint64_t float_count =
      tonic::DartConverter<uint64_t>::FromDart(float_count_handle);
  uint64_t sampler_count =
      tonic::DartConverter<uint64_t>::FromDart(sampler_count_handle);

  auto res = fml::MakeRefCounted<ReusableFragmentShader>(
      fml::Ref(fragment_program), float_count, sampler_count);
  res->AssociateWithDartWrapper(wrapper);

  void* raw_uniform_data =
      reinterpret_cast<void*>(res->uniform_data_->writable_data());
  return Dart_NewExternalTypedData(Dart_TypedData_kFloat32, raw_uniform_data,
                                   float_count);
}

void ReusableFragmentShader::SetSampler(Dart_Handle index_handle,
                                        Dart_Handle sampler_handle) {
  uint64_t index = tonic::DartConverter<uint64_t>::FromDart(index_handle);
  ImageShader* sampler =
      tonic::DartConverter<ImageShader*>::FromDart(sampler_handle);
  if (index >= samplers_.size()) {
    Dart_ThrowException(tonic::ToDart("Sampler index out of bounds"));
  }

  // ImageShaders can hold a preferred value for sampling options and
  // developers are encouraged to use that value or the value will be supplied
  // by "the environment where it is used". The environment here does not
  // contain a value to be used if the developer did not specify a preference
  // when they constructed the ImageShader, so we will use kNearest which is
  // the default filterQuality in a Paint object.
  DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
  auto* uniform_floats =
      reinterpret_cast<float*>(uniform_data_->writable_data());
  samplers_[index] = sampler->shader(sampling);
  uniform_floats[float_count_ + 2 * index] = sampler->width();
  uniform_floats[float_count_ + 2 * index + 1] = sampler->height();
}

std::shared_ptr<DlColorSource> ReusableFragmentShader::shader(
    DlImageSampling sampling) {
  FML_CHECK(program_);
  return program_->MakeDlColorSource(uniform_data_, samplers_);
}

void ReusableFragmentShader::Dispose() {
  uniform_data_.reset();
  program_ = nullptr;
  samplers_.clear();
  ClearDartWrapper();
}

ReusableFragmentShader::~ReusableFragmentShader() = default;

}  // namespace flutter
