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

#include <array>
#include <filesystem>
#include <optional>

#include "impeller/blobcat/blob_flatbuffers.h"

namespace impeller {

BlobWriter::BlobWriter() = default;

BlobWriter::~BlobWriter() = default;

std::optional<BlobShaderType> InferShaderTypefromFileExtension(
    const std::filesystem::path& path) {
  if (path == ".vert") {
    return BlobShaderType::kVertex;
  } else if (path == ".frag") {
    return BlobShaderType::kFragment;
  } else if (path == ".comp") {
    return BlobShaderType::kCompute;
  }
  return std::nullopt;
}

bool BlobWriter::AddBlobAtPath(const std::string& std_path) {
  std::filesystem::path path(std_path);

  if (path.stem().empty()) {
    FML_LOG(ERROR) << "File path stem was empty for " << path;
    return false;
  }

  if (path.extension() != ".gles" && path.extension() != ".vkspv") {
    FML_LOG(ERROR) << "File path doesn't have a known shader extension "
                   << path;
    return false;
  }

  // Get rid of .gles
  path = path.replace_extension();

  auto shader_type = InferShaderTypefromFileExtension(path.extension());

  if (!shader_type.has_value()) {
    FML_LOG(ERROR) << "Could not infer shader type from file extension: "
                   << path.extension().string();
    return false;
  }

  // Get rid of the shader type extension (.vert, .frag, etc..).
  path = path.replace_extension();

  const auto shader_name = path.stem().string();
  if (shader_name.empty()) {
    FML_LOG(ERROR) << "Shader name was empty.";
    return false;
  }

  auto file_mapping = fml::FileMapping::CreateReadOnly(std_path);
  if (!file_mapping) {
    FML_LOG(ERROR) << "File doesn't exist at path: " << path;
    return false;
  }

  return AddBlob(shader_type.value(), std::move(shader_name),
                 std::move(file_mapping));
}

bool BlobWriter::AddBlob(BlobShaderType type,
                         std::string name,
                         std::shared_ptr<fml::Mapping> mapping) {
  if (name.empty() || !mapping || mapping->GetMapping() == nullptr) {
    return false;
  }

  blob_descriptions_.emplace_back(
      BlobDescription{type, std::move(name), std::move(mapping)});
  return true;
}

constexpr fb::Stage ToStage(BlobShaderType type) {
  switch (type) {
    case BlobShaderType::kVertex:
      return fb::Stage::kVertex;
    case BlobShaderType::kFragment:
      return fb::Stage::kFragment;
    case BlobShaderType::kCompute:
      return fb::Stage::kCompute;
  }
  FML_UNREACHABLE();
}

std::shared_ptr<fml::Mapping> BlobWriter::CreateMapping() const {
  fb::BlobLibraryT blobs;
  for (const auto& blob_description : blob_descriptions_) {
    auto mapping = blob_description.mapping;
    if (!mapping) {
      return nullptr;
    }
    auto desc = std::make_unique<fb::BlobT>();
    desc->name = blob_description.name;
    desc->stage = ToStage(blob_description.type);
    desc->mapping = {mapping->GetMapping(),
                     mapping->GetMapping() + mapping->GetSize()};
    blobs.items.emplace_back(std::move(desc));
  }
  auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
  builder->Finish(fb::BlobLibrary::Pack(*builder.get(), &blobs),
                  fb::BlobLibraryIdentifier());
  return std::make_shared<fml::NonOwnedMapping>(builder->GetBufferPointer(),
                                                builder->GetSize(),
                                                [builder](auto, auto) {});
}

}  // namespace impeller
