// 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 <filesystem>
#include <optional>

namespace impeller {

BlobWriter::BlobWriter() = default;

BlobWriter::~BlobWriter() = default;

std::optional<Blob::ShaderType> InferShaderTypefromFileExtension(
    const std::filesystem::path& path) {
  if (path == ".vert") {
    return Blob::ShaderType::kVertex;
  } else if (path == ".frag") {
    return Blob::ShaderType::kFragment;
  }
  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(Blob::ShaderType type,
                         std::string name,
                         std::shared_ptr<fml::Mapping> mapping) {
  if (name.empty() || !mapping || mapping->GetMapping() == nullptr) {
    return false;
  }

  if (name.length() >= Blob::kMaxNameLength) {
    FML_LOG(ERROR) << "Blob name length was too long.";
    return false;
  }

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

std::shared_ptr<fml::Mapping> BlobWriter::CreateMapping() const {
  BlobHeader header;
  header.blob_count = blob_descriptions_.size();

  uint64_t offset = sizeof(BlobHeader) + (sizeof(Blob) * header.blob_count);

  std::vector<Blob> blobs;
  {
    blobs.resize(header.blob_count);
    for (size_t i = 0; i < header.blob_count; i++) {
      const auto& desc = blob_descriptions_[i];
      blobs[i].type = desc.type;
      blobs[i].offset = offset;
      blobs[i].length = desc.mapping->GetSize();
      std::memcpy(reinterpret_cast<void*>(blobs[i].name), desc.name.data(),
                  desc.name.size());
      offset += blobs[i].length;
    }
  }

  {
    auto buffer = std::make_shared<std::vector<uint8_t>>();
    buffer->resize(offset, 0);

    size_t write_offset = 0u;

    // Write the header.
    {
      const size_t write_length = sizeof(header);
      std::memcpy(buffer->data() + write_offset, &header, write_length);
      write_offset += write_length;
    }

    // Write the blob descriptions.
    {
      const size_t write_length = blobs.size() * sizeof(Blob);
      std::memcpy(buffer->data() + write_offset, blobs.data(), write_length);
      write_offset += write_length;
    }

    // Write the blobs themselves.
    {
      for (size_t i = 0; i < header.blob_count; i++) {
        const auto& desc = blob_descriptions_[i];
        const size_t write_length = desc.mapping->GetSize();
        std::memcpy(buffer->data() + write_offset, desc.mapping->GetMapping(),
                    write_length);
        write_offset += write_length;
      }
    }
    FML_CHECK(write_offset == offset);
    return std::make_shared<fml::NonOwnedMapping>(
        buffer->data(), buffer->size(),
        [buffer](const uint8_t* data, size_t size) {});
  }
  return nullptr;
}

}  // namespace impeller
