// 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 "impeller/scene/material.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/sampler_descriptor.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/scene/importer/conversions.h"
#include "impeller/scene/importer/scene_flatbuffers.h"
#include "impeller/scene/pipeline_key.h"
#include "impeller/scene/scene_context.h"
#include "impeller/scene/shaders/unlit.frag.h"

#include <memory>

namespace impeller {
namespace scene {

//------------------------------------------------------------------------------
/// Material
///

Material::~Material() = default;

std::unique_ptr<Material> Material::MakeFromFlatbuffer(
    const fb::Material& material,
    const std::vector<std::shared_ptr<Texture>>& textures) {
  switch (material.type()) {
    case fb::MaterialType::kUnlit:
      return UnlitMaterial::MakeFromFlatbuffer(material, textures);
    case fb::MaterialType::kPhysicallyBased:
      return PhysicallyBasedMaterial::MakeFromFlatbuffer(material, textures);
  }
}

std::unique_ptr<UnlitMaterial> Material::MakeUnlit() {
  return std::make_unique<UnlitMaterial>();
}

std::unique_ptr<PhysicallyBasedMaterial> Material::MakePhysicallyBased() {
  return std::make_unique<PhysicallyBasedMaterial>();
}

void Material::SetVertexColorWeight(Scalar weight) {
  vertex_color_weight_ = weight;
}

void Material::SetBlendConfig(BlendConfig blend_config) {
  blend_config_ = blend_config;
}

void Material::SetStencilConfig(StencilConfig stencil_config) {
  stencil_config_ = stencil_config;
}

void Material::SetTranslucent(bool is_translucent) {
  is_translucent_ = is_translucent;
}

SceneContextOptions Material::GetContextOptions(const RenderPass& pass) const {
  // TODO(bdero): Pipeline blend and stencil config.
  return {.sample_count = pass.GetRenderTarget().GetSampleCount()};
}

//------------------------------------------------------------------------------
/// UnlitMaterial
///

std::unique_ptr<UnlitMaterial> UnlitMaterial::MakeFromFlatbuffer(
    const fb::Material& material,
    const std::vector<std::shared_ptr<Texture>>& textures) {
  if (material.type() != fb::MaterialType::kUnlit) {
    VALIDATION_LOG << "Cannot unpack unlit material because the ipscene "
                      "material type is not unlit.";
    return nullptr;
  }

  auto result = Material::MakeUnlit();

  if (material.base_color_factor()) {
    result->SetColor(importer::ToColor(*material.base_color_factor()));
  }

  if (material.base_color_texture() >= 0 &&
      material.base_color_texture() < static_cast<int32_t>(textures.size())) {
    result->SetColorTexture(textures[material.base_color_texture()]);
  }

  return result;
}

UnlitMaterial::~UnlitMaterial() = default;

void UnlitMaterial::SetColor(Color color) {
  color_ = color;
}

void UnlitMaterial::SetColorTexture(std::shared_ptr<Texture> color_texture) {
  color_texture_ = std::move(color_texture);
}

// |Material|
MaterialType UnlitMaterial::GetMaterialType() const {
  return MaterialType::kUnlit;
}

// |Material|
void UnlitMaterial::BindToCommand(const SceneContext& scene_context,
                                  HostBuffer& buffer,
                                  RenderPass& pass) const {
  // Uniform buffer.
  UnlitFragmentShader::FragInfo info;
  info.color = color_;
  info.vertex_color_weight = vertex_color_weight_;
  UnlitFragmentShader::BindFragInfo(pass, buffer.EmplaceUniform(info));

  // Textures.
  SamplerDescriptor sampler_descriptor;
  sampler_descriptor.label = "Trilinear";
  sampler_descriptor.min_filter = MinMagFilter::kLinear;
  sampler_descriptor.mag_filter = MinMagFilter::kLinear;
  sampler_descriptor.mip_filter = MipFilter::kLinear;
  UnlitFragmentShader::BindBaseColorTexture(
      pass,
      color_texture_ ? color_texture_ : scene_context.GetPlaceholderTexture(),
      scene_context.GetContext()->GetSamplerLibrary()->GetSampler(
          sampler_descriptor));
}

//------------------------------------------------------------------------------
/// StandardMaterial
///

std::unique_ptr<PhysicallyBasedMaterial>
PhysicallyBasedMaterial::MakeFromFlatbuffer(
    const fb::Material& material,
    const std::vector<std::shared_ptr<Texture>>& textures) {
  if (material.type() != fb::MaterialType::kPhysicallyBased) {
    VALIDATION_LOG << "Cannot unpack unlit material because the ipscene "
                      "material type is not unlit.";
    return nullptr;
  }

  auto result = Material::MakePhysicallyBased();

  result->SetAlbedo(material.base_color_factor()
                        ? importer::ToColor(*material.base_color_factor())
                        : Color::White());
  result->SetRoughness(material.roughness_factor());
  result->SetMetallic(material.metallic_factor());

  if (material.base_color_texture() >= 0 &&
      material.base_color_texture() < static_cast<int32_t>(textures.size())) {
    result->SetAlbedoTexture(textures[material.base_color_texture()]);
    result->SetVertexColorWeight(0);
  }
  if (material.metallic_roughness_texture() >= 0 &&
      material.metallic_roughness_texture() <
          static_cast<int32_t>(textures.size())) {
    result->SetMetallicRoughnessTexture(
        textures[material.metallic_roughness_texture()]);
  }
  if (material.normal_texture() >= 0 &&
      material.normal_texture() < static_cast<int32_t>(textures.size())) {
    result->SetNormalTexture(textures[material.normal_texture()]);
  }
  if (material.occlusion_texture() >= 0 &&
      material.occlusion_texture() < static_cast<int32_t>(textures.size())) {
    result->SetOcclusionTexture(textures[material.occlusion_texture()]);
  }

  return result;
}

PhysicallyBasedMaterial::~PhysicallyBasedMaterial() = default;

void PhysicallyBasedMaterial::SetAlbedo(Color albedo) {
  albedo_ = albedo;
}

void PhysicallyBasedMaterial::SetRoughness(Scalar roughness) {
  roughness_ = roughness;
}

void PhysicallyBasedMaterial::SetMetallic(Scalar metallic) {
  metallic_ = metallic;
}

void PhysicallyBasedMaterial::SetAlbedoTexture(
    std::shared_ptr<Texture> albedo_texture) {
  albedo_texture_ = std::move(albedo_texture);
}

void PhysicallyBasedMaterial::SetMetallicRoughnessTexture(
    std::shared_ptr<Texture> metallic_roughness_texture) {
  metallic_roughness_texture_ = std::move(metallic_roughness_texture);
}

void PhysicallyBasedMaterial::SetNormalTexture(
    std::shared_ptr<Texture> normal_texture) {
  normal_texture_ = std::move(normal_texture);
}

void PhysicallyBasedMaterial::SetOcclusionTexture(
    std::shared_ptr<Texture> occlusion_texture) {
  occlusion_texture_ = std::move(occlusion_texture);
}

void PhysicallyBasedMaterial::SetEnvironmentMap(
    std::shared_ptr<Texture> environment_map) {
  environment_map_ = std::move(environment_map);
}

// |Material|
MaterialType PhysicallyBasedMaterial::GetMaterialType() const {
  // TODO(bdero): Replace this once a PBR shader has landed.
  return MaterialType::kUnlit;
}

// |Material|
void PhysicallyBasedMaterial::BindToCommand(const SceneContext& scene_context,
                                            HostBuffer& buffer,
                                            RenderPass& pass) const {}

}  // namespace scene
}  // namespace impeller
