// 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_program.h"

#include "flutter/lib/ui/dart_wrapper.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"

using tonic::ToDart;

namespace flutter {

static void FragmentProgram_constructor(Dart_NativeArguments args) {
  DartCallConstructor(&FragmentProgram::Create, args);
}

IMPLEMENT_WRAPPERTYPEINFO(ui, FragmentProgram);

#define FOR_EACH_BINDING(V) \
  V(FragmentProgram, init)  \
  V(FragmentProgram, shader)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void FragmentProgram::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register(
      {{"FragmentProgram_constructor", FragmentProgram_constructor, 1, true},
       FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

void FragmentProgram::init(std::string sksl, bool debugPrintSksl) {
  SkRuntimeEffect::Result result =
      SkRuntimeEffect::MakeForShader(SkString(sksl));
  runtime_effect_ = result.effect;

  if (runtime_effect_ == nullptr) {
    Dart_ThrowException(tonic::ToDart(
        std::string("Invalid SkSL:\n") + sksl.c_str() +
        std::string("\nSkSL Error:\n") + result.errorText.c_str()));
    return;
  }
  if (debugPrintSksl) {
    FML_DLOG(INFO) << std::string("debugPrintSksl:\n") + sksl.c_str();
  }
}

fml::RefPtr<FragmentShader> FragmentProgram::shader(
    Dart_Handle shader,
    const tonic::Float32List& uniforms,
    Dart_Handle samplers) {
  auto sampler_shaders =
      tonic::DartConverter<std::vector<ImageShader*>>::FromDart(samplers);
  size_t uniform_count = uniforms.num_elements();
  size_t uniform_data_size =
      (uniform_count + 2 * sampler_shaders.size()) * sizeof(float);
  sk_sp<SkData> uniform_data = SkData::MakeUninitialized(uniform_data_size);
  // uniform_floats must only be referenced BEFORE the call to makeShader below.
  auto* uniform_floats =
      reinterpret_cast<float*>(uniform_data->writable_data());
  for (size_t i = 0; i < uniform_count; i++) {
    uniform_floats[i] = uniforms[i];
  }
  std::vector<sk_sp<SkShader>> sk_samplers(sampler_shaders.size());
  for (size_t i = 0; i < sampler_shaders.size(); i++) {
    ImageShader* image_shader = sampler_shaders[i];
    // The default value for SkSamplingOptions is used because ImageShader
    // uses a cached value set by the user in the Dart constructor.
    // Users are instructed to make use of this in the Dart docs.
    sk_samplers[i] = image_shader->shader(SkSamplingOptions());
    uniform_floats[uniform_count + 2 * i] = image_shader->width();
    uniform_floats[uniform_count + 2 * i + 1] = image_shader->height();
  }
  auto sk_shader =
      runtime_effect_->makeShader(std::move(uniform_data), sk_samplers.data(),
                                  sk_samplers.size(), nullptr, false);
  return FragmentShader::Create(shader, std::move(sk_shader));
}

fml::RefPtr<FragmentProgram> FragmentProgram::Create() {
  return fml::MakeRefCounted<FragmentProgram>();
}

FragmentProgram::FragmentProgram() = default;

FragmentProgram::~FragmentProgram() = default;

}  // namespace flutter
