// 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 "jumbf/box_builder.h"

#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <utility>

#include "absl/algorithm/container.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "jumbf/constants.h"
#include "jumbf/encode_params.h"
#include "jumbf/internal/encode.h"
#include "uuid/uuid.h"

namespace jumbf {

SuperBoxBuilder::SuperBoxBuilder(credentio::Uuid type_uuid,
                                 DescriptionBoxOptions description_options)
    : type_uuid_(std::move(type_uuid)),
      description_label_(description_options.label),
      description_options_(std::move(description_options)) {
  if (description_label_.has_value()) {
    description_label_->Flatten();
  }
}

absl::Status SuperBoxBuilder::AssertStateIn(
    absl::Span<const SuperBoxBuildingState> want) const {
  if (absl::c_linear_search(want, state_)) {
    return absl::OkStatus();
  }

  std::string want_str;
  if (want.size() == 1) {
    want_str = absl::StrCat(want[0]);
  } else {
    want_str = absl::StrCat("one of [", absl::StrJoin(want, ", "), "]");
  }
  return absl::FailedPreconditionError(
      absl::StrCat("builder in invalid state for operation: got: ", state_,
                   ", want: ", want_str));
}

void SuperBoxBuilder::StateTransition(
    absl::Span<const SuperBoxBuildingState> from, SuperBoxBuildingState to) {
  if (absl::c_linear_search(from, state_)) {
    state_ = to;
  }
}

absl::Status SuperBoxBuilder::AddPadding(size_t len) {
  ABSL_RETURN_IF_ERROR(AssertStateIn({SuperBoxBuildingState::kEmpty}));
  StateTransition({SuperBoxBuildingState::kEmpty},
                  SuperBoxBuildingState::kContainsPadding);
  return EncodePaddingBox(len, &writer_);
}

absl::Status SuperBoxBuilder::AddChild(SuperBoxBuilder&& child) {
  ABSL_RETURN_IF_ERROR(AssertStateIn(
      {SuperBoxBuildingState::kEmpty, SuperBoxBuildingState::kContainsPadding,
       SuperBoxBuildingState::kContainsContent}));
  StateTransition(
      {SuperBoxBuildingState::kEmpty, SuperBoxBuildingState::kContainsPadding},
      SuperBoxBuildingState::kContainsContent);

  ABSL_ASSIGN_OR_RETURN(auto serialized_child, std::move(child).Finalize());
  return AddChild(std::move(serialized_child));
};

absl::Status SuperBoxBuilder::AddContent(uint32_t tbox, absl::Cord payload) {
  ABSL_RETURN_IF_ERROR(AssertStateIn(
      {SuperBoxBuildingState::kEmpty, SuperBoxBuildingState::kContainsPadding,
       SuperBoxBuildingState::kContainsContent}));
  StateTransition(
      {SuperBoxBuildingState::kEmpty, SuperBoxBuildingState::kContainsPadding},
      SuperBoxBuildingState::kContainsContent);
  return EncodeContentBox(tbox, std::move(payload), &writer_);
}

absl::Status SuperBoxBuilder::AddChild(BuiltSuperBox&& serialized_superbox) {
  StateTransition(
      {SuperBoxBuildingState::kEmpty, SuperBoxBuildingState::kContainsPadding},
      SuperBoxBuildingState::kContainsContent);
  return EncodeSerializedSuperBox(std::move(serialized_superbox).AsCord(),
                                  &writer_);
}

absl::Status SuperBoxBuilder::AddChild(absl::Cord serialized_superbox) {
  StateTransition(
      {SuperBoxBuildingState::kEmpty, SuperBoxBuildingState::kContainsPadding},
      SuperBoxBuildingState::kContainsContent);
  return EncodeSerializedSuperBox(std::move(serialized_superbox), &writer_);
}

absl::StatusOr<BuiltSuperBox> SuperBoxBuilder::Finalize() && {
  // JUMBF requires at least one content box.
  ABSL_RETURN_IF_ERROR(
      AssertStateIn({SuperBoxBuildingState::kContainsContent}));

  ABSL_RETURN_IF_ERROR(EncodeDescriptionBox(
      std::move(type_uuid_), std::move(description_options_), &writer_));
  ABSL_RETURN_IF_ERROR(EncodeBoxHeader(writer_.pos(), kSuperBoxType, &writer_));
  if (!writer_.Close()) {
    return writer_.status();
  }

  std::optional<std::string> description_label;
  if (description_label_.has_value()) {
    description_label = std::string(*description_label_);
  }
  auto result =
      BuiltSuperBox(std::move(writer_.dest()), std::move(description_label));

  // Clear out everything to Builder in a reasonable state post-move:
  state_ = SuperBoxBuildingState::kEmpty;
  writer_.Reset();
  return result;
}

}  // namespace jumbf
