// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "formats/gif/test_builder.h"

#include <algorithm>
#include <cmath>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>

#include "formats/gif/constants.h"

namespace credentio {
namespace {

std::string EncodeDataToBlocks(std::string data,
                               bool add_termination_block = true) {
  std::vector<uint8_t> blocks;
  blocks.reserve(data.size() + std::ceil(data.size() / 255.0) + 1);

  for (int64_t i = 0; i < data.size(); i += 255) {
    int64_t block_size = std::min<int64_t>(255, data.size() - i);
    blocks.push_back(static_cast<uint8_t>(block_size));
    blocks.insert(blocks.end(), data.begin() + i,
                  data.begin() + i + block_size);
  }
  if (add_termination_block) {
    blocks.push_back(0);  // Add a zero-length block to signify the end.
  }
  return std::string(blocks.begin(), blocks.end());
}

}  // namespace

void TestGifBuilder::AddGifHeader() { gif_data_ += "GIF89a"; }

void TestGifBuilder::AddLogicalDescriptor(bool has_color_table) {
  uint8_t packedField = has_color_table ? 0x91 : 0x00;
  uint8_t backgroundColorIndex = has_color_table ? 0x11 : 0x00;

  std::vector<uint8_t> lsd = {1, 1, 2, 2, packedField, backgroundColorIndex, 0};
  gif_data_ += std::string(lsd.begin(), lsd.end());

  if (has_color_table) {
    std::vector<uint8_t> color_table = {
        0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
    };
    gif_data_ += std::string(color_table.begin(), color_table.end());
  }
}

void TestGifBuilder::AddImageDescriptor(bool has_color_table) {
  uint8_t packedField = has_color_table ? 0x91 : 0x00;

  std::vector<uint8_t> lsd = {
      kGifImageDescriptorIntroducer, 1, 1, 1, 1, 1, 1, 1, 1, packedField};
  gif_data_ += std::string(lsd.begin(), lsd.end());

  if (has_color_table) {
    std::vector<uint8_t> color_table = {
        0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
    };
    gif_data_ += std::string(color_table.begin(), color_table.end());
  }
}

void TestGifBuilder::AddBlock(uint8_t introducer, std::optional<uint8_t> type,
                              std::optional<std::string> info,
                              std::optional<std::string> data) {
  gif_data_ += static_cast<char>(introducer);

  if (type.has_value()) {
    gif_data_ += static_cast<char>(type.value());
  }

  if (info.has_value()) {
    gif_data_ +=
        EncodeDataToBlocks(info.value(), /*add_termination_block=*/false);
  }

  if (data.has_value()) {
    gif_data_ += EncodeDataToBlocks(data.value());
  }
}

std::string TestGifBuilder::GetAsset() { return gif_data_; }

}  // namespace credentio
