// 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 "flutter/lib/gpu/shader_library.h"

#include <utility>

#include "flutter/lib/gpu/fixtures.h"
#include "flutter/lib/gpu/shader.h"
#include "fml/mapping.h"
#include "fml/memory/ref_ptr.h"
#include "impeller/renderer/vertex_descriptor.h"
#include "impeller/runtime_stage/runtime_stage.h"

namespace flutter {
namespace gpu {

// ===[ BEGIN MEMES ]===========================================================
static fml::RefPtr<Shader> OpenRuntimeStageAsShader(
    std::shared_ptr<fml::Mapping> payload,
    const std::shared_ptr<impeller::VertexDescriptor>& vertex_desc) {
  impeller::RuntimeStage stage(std::move(payload));
  return Shader::Make(stage.GetEntrypoint(),
                      ToShaderStage(stage.GetShaderStage()),
                      stage.GetCodeMapping(), stage.GetUniforms(), vertex_desc);
}

static fml::RefPtr<ShaderLibrary> InstantiateTestShaderLibrary() {
  ShaderLibrary::ShaderMap shaders;
  {
    auto vertex_desc = std::make_shared<impeller::VertexDescriptor>();
    vertex_desc->SetStageInputs(
        FlutterGPUUnlitVertexShader::kAllShaderStageInputs,
        FlutterGPUUnlitVertexShader::kInterleavedBufferLayout);
    shaders["UnlitVertex"] = OpenRuntimeStageAsShader(
        std::make_shared<fml::NonOwnedMapping>(kFlutterGPUUnlitVertIPLR,
                                               kFlutterGPUUnlitVertIPLRLength),
        vertex_desc);
    shaders["UnlitFragment"] = OpenRuntimeStageAsShader(
        std::make_shared<fml::NonOwnedMapping>(kFlutterGPUUnlitFragIPLR,
                                               kFlutterGPUUnlitFragIPLRLength),
        nullptr);
  }
  {
    auto vertex_desc = std::make_shared<impeller::VertexDescriptor>();
    vertex_desc->SetStageInputs(
        FlutterGPUTextureVertexShader::kAllShaderStageInputs,
        FlutterGPUTextureVertexShader::kInterleavedBufferLayout);
    shaders["TextureVertex"] = OpenRuntimeStageAsShader(
        std::make_shared<fml::NonOwnedMapping>(
            kFlutterGPUTextureVertIPLR, kFlutterGPUTextureVertIPLRLength),
        vertex_desc);
    shaders["TextureFragment"] = OpenRuntimeStageAsShader(
        std::make_shared<fml::NonOwnedMapping>(
            kFlutterGPUTextureFragIPLR, kFlutterGPUTextureFragIPLRLength),
        nullptr);
  }
  auto library = ShaderLibrary::MakeFromShaders(std::move(shaders));
  return library;
}
// ===[ END MEMES ]=============================================================

IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, ShaderLibrary);

fml::RefPtr<ShaderLibrary> ShaderLibrary::override_shader_library_;

fml::RefPtr<ShaderLibrary> ShaderLibrary::MakeFromAsset(
    const std::string& name,
    std::string& out_error) {
  // ===========================================================================
  // This is a temporary hack to get the shader library populated in the
  // framework before the shader bundle format is landed!
  if (!override_shader_library_) {
    return InstantiateTestShaderLibrary();
  }
  // ===========================================================================

  if (override_shader_library_) {
    return override_shader_library_;
  }
  // TODO(bdero): Load the ShaderLibrary asset.
  out_error = "Shader bundle asset unimplemented";
  return nullptr;
}

fml::RefPtr<ShaderLibrary> ShaderLibrary::MakeFromShaders(ShaderMap shaders) {
  auto res =
      fml::MakeRefCounted<flutter::gpu::ShaderLibrary>(std::move(shaders));
  return res;
}

void ShaderLibrary::SetOverride(
    fml::RefPtr<ShaderLibrary> override_shader_library) {
  override_shader_library_ = std::move(override_shader_library);
}

fml::RefPtr<Shader> ShaderLibrary::GetShader(const std::string& shader_name,
                                             Dart_Handle shader_wrapper) const {
  auto it = shaders_.find(shader_name);
  if (it == shaders_.end()) {
    return nullptr;  // No matching shaders.
  }
  auto shader = it->second;

  if (shader->dart_wrapper() == nullptr) {
    shader->AssociateWithDartWrapper(shader_wrapper);
  }
  return shader;
}

ShaderLibrary::ShaderLibrary(ShaderMap shaders)
    : shaders_(std::move(shaders)) {}

ShaderLibrary::~ShaderLibrary() = default;

}  // namespace gpu
}  // namespace flutter

//----------------------------------------------------------------------------
/// Exports
///

Dart_Handle InternalFlutterGpu_ShaderLibrary_InitializeWithAsset(
    Dart_Handle wrapper,
    Dart_Handle asset_name) {
  if (!Dart_IsString(asset_name)) {
    return tonic::ToDart("Asset name must be a string");
  }

  std::string error;
  auto res = flutter::gpu::ShaderLibrary::MakeFromAsset(
      tonic::StdStringFromDart(asset_name), error);
  if (!res) {
    return tonic::ToDart(error);
  }
  res->AssociateWithDartWrapper(wrapper);
  return Dart_Null();
}

Dart_Handle InternalFlutterGpu_ShaderLibrary_GetShader(
    flutter::gpu::ShaderLibrary* wrapper,
    Dart_Handle shader_name,
    Dart_Handle shader_wrapper) {
  FML_DCHECK(Dart_IsString(shader_name));
  auto shader =
      wrapper->GetShader(tonic::StdStringFromDart(shader_name), shader_wrapper);
  if (!shader) {
    return Dart_Null();
  }
  return tonic::ToDart(shader.get());
}
