// 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/renderer/backend/gles/shader_library_gles.h"

#include <sstream>

#include "flutter/fml/closure.h"
#include "impeller/base/config.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/gles/shader_function_gles.h"
#include "impeller/shader_archive/multi_arch_shader_archive.h"
#include "impeller/shader_archive/shader_archive.h"

namespace impeller {

static ShaderStage ToShaderStage(ArchiveShaderType type) {
  switch (type) {
    case ArchiveShaderType::kVertex:
      return ShaderStage::kVertex;
    case ArchiveShaderType::kFragment:
      return ShaderStage::kFragment;
    case ArchiveShaderType::kCompute:
      return ShaderStage::kCompute;
  }
  FML_UNREACHABLE();
}

static std::string GLESShaderNameToShaderKeyName(const std::string& name,
                                                 ShaderStage stage) {
  std::stringstream stream;
  stream << name;
  switch (stage) {
    case ShaderStage::kUnknown:
      stream << "_unknown_";
      break;
    case ShaderStage::kVertex:
      stream << "_vertex_";
      break;
    case ShaderStage::kFragment:
      stream << "_fragment_";
      break;
    case ShaderStage::kCompute:
      stream << "_compute_";
      break;
  }
  stream << "main";
  return stream.str();
}

ShaderLibraryGLES::ShaderLibraryGLES(
    const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries) {
  ShaderFunctionMap functions;
  auto iterator = [&functions, library_id = library_id_](auto type,           //
                                                         const auto& name,    //
                                                         const auto& mapping  //
                                                         ) -> bool {
    const auto stage = ToShaderStage(type);
    const auto key_name = GLESShaderNameToShaderKeyName(name, stage);

    functions[ShaderKey{key_name, stage}] = std::shared_ptr<ShaderFunctionGLES>(
        new ShaderFunctionGLES(library_id,  //
                               stage,       //
                               key_name,    //
                               mapping      //
                               ));

    return true;
  };
  for (auto library : shader_libraries) {
    auto gles_archive = MultiArchShaderArchive::CreateArchiveFromMapping(
        std::move(library), ArchiveRenderingBackend::kOpenGLES);
    if (!gles_archive || !gles_archive->IsValid()) {
      VALIDATION_LOG << "Could not construct shader library.";
      return;
    }
    gles_archive->IterateAllShaders(iterator);
  }

  functions_ = functions;
  is_valid_ = true;
}

// |ShaderLibrary|
ShaderLibraryGLES::~ShaderLibraryGLES() = default;

// |ShaderLibrary|
bool ShaderLibraryGLES::IsValid() const {
  return is_valid_;
}

// |ShaderLibrary|
std::shared_ptr<const ShaderFunction> ShaderLibraryGLES::GetFunction(
    std::string_view name,
    ShaderStage stage) {
  ReaderLock lock(functions_mutex_);
  const auto key = ShaderKey{name, stage};
  if (auto found = functions_.find(key); found != functions_.end()) {
    return found->second;
  }
  return nullptr;
}

// |ShaderLibrary|
void ShaderLibraryGLES::RegisterFunction(std::string name,
                                         ShaderStage stage,
                                         std::shared_ptr<fml::Mapping> code,
                                         RegistrationCallback callback) {
  if (!callback) {
    callback = [](auto) {};
  }
  fml::ScopedCleanupClosure auto_fail([callback]() { callback(false); });
  if (name.empty() || stage == ShaderStage::kUnknown || code == nullptr ||
      code->GetMapping() == nullptr) {
    VALIDATION_LOG << "Invalid runtime stage registration.";
    return;
  }
  const auto key = ShaderKey{name, stage};
  WriterLock lock(functions_mutex_);
  if (functions_.count(key) != 0) {
    VALIDATION_LOG << "Runtime stage named " << name
                   << " has already been registered.";
    return;
  }
  functions_[key] = std::shared_ptr<ShaderFunctionGLES>(new ShaderFunctionGLES(
      library_id_,                                 //
      stage,                                       //
      GLESShaderNameToShaderKeyName(name, stage),  //
      code                                         //
      ));
  auto_fail.Release();
  callback(true);
}

// |ShaderLibrary|
void ShaderLibraryGLES::UnregisterFunction(std::string name,
                                           ShaderStage stage) {
  ReaderLock lock(functions_mutex_);

  const auto key = ShaderKey{name, stage};

  auto found = functions_.find(key);
  if (found != functions_.end()) {
    VALIDATION_LOG << "Library function named " << name
                   << " was not found, so it couldn't be unregistered.";
    return;
  }

  functions_.erase(found);

  return;
}

}  // namespace impeller
