// Copyright 2021 The Pigweed Authors
//
// 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 "pw_software_update/manifest_accessor.h"

#include "pw_software_update/config.h"
#include "pw_software_update/update_bundle.pwpb.h"
#include "pw_software_update/update_bundle_accessor.h"

namespace pw::software_update {

ManifestAccessor ManifestAccessor::FromBundle(protobuf::Message bundle) {
  protobuf::Message targets_metadata =
      bundle
          .AsStringToMessageMap(static_cast<uint32_t>(
              UpdateBundle::Fields::TARGETS_METADATA))[kTopLevelTargetsName]
          .AsMessage(static_cast<uint32_t>(
              SignedTargetsMetadata::Fields::SERIALIZED_TARGETS_METADATA));

  protobuf::Bytes user_manifest =
      bundle.AsStringToBytesMap(static_cast<uint32_t>(
          UpdateBundle::Fields::TARGET_PAYLOADS))[kUserManifestTargetFileName];

  return ManifestAccessor(targets_metadata, user_manifest);
}

ManifestAccessor ManifestAccessor::FromManifest(protobuf::Message manifest) {
  protobuf::Message targets_metadata =
      manifest.AsStringToMessageMap(static_cast<uint32_t>(
          Manifest::Fields::TARGETS_METADATA))[kTopLevelTargetsName];

  protobuf::Bytes user_manifest =
      manifest.AsBytes(static_cast<uint32_t>(Manifest::Fields::USER_MANIFEST));

  return ManifestAccessor(targets_metadata, user_manifest);
}

protobuf::RepeatedMessages ManifestAccessor::GetTargetFiles() {
  PW_TRY(status());
  return targets_metadata_.AsRepeatedMessages(
      static_cast<uint32_t>(TargetsMetadata::Fields::TARGET_FILES));
}

protobuf::Uint32 ManifestAccessor::GetVersion() {
  PW_TRY(status());
  return targets_metadata_
      .AsMessage(
          static_cast<uint32_t>(TargetsMetadata::Fields::COMMON_METADATA))
      .AsUint32(static_cast<uint32_t>(CommonMetadata::Fields::VERSION));
}

Status ManifestAccessor::Export(stream::Writer& writer) {
  PW_TRY(status());

  // Write out the targets metadata map.
  stream::MemoryReader name_reader(
      std::as_bytes(std::span(kTopLevelTargetsName)));
  stream::IntervalReader metadata_reader =
      targets_metadata_.ToBytes().GetBytesReader();
  std::byte stream_pipe_buffer[WRITE_MANIFEST_STREAM_PIPE_BUFFER_SIZE];
  PW_TRY(protobuf::WriteProtoStringToBytesMapEntry(
      static_cast<uint32_t>(Manifest::Fields::TARGETS_METADATA),
      name_reader,
      kTopLevelTargetsName.size(),
      metadata_reader,
      metadata_reader.interval_size(),
      stream_pipe_buffer,
      writer));

  // The user manifest is optional, write it out if available().
  stream::IntervalReader user_manifest_reader = user_manifest_.GetBytesReader();
  if (user_manifest_reader.ok()) {
    protobuf::StreamEncoder encoder(writer, {});
    PW_TRY(encoder.WriteBytesFromStream(
        static_cast<uint32_t>(Manifest::Fields::USER_MANIFEST),
        user_manifest_reader,
        user_manifest_reader.interval_size(),
        stream_pipe_buffer));
  }

  return OkStatus();
}

protobuf::Message ManifestAccessor::GetTargetFile(protobuf::String name) {
  PW_TRY(status());

  std::array<std::byte, MAX_TARGET_NAME_LENGTH> name_buf = {};

  stream::IntervalReader name_reader = name.GetBytesReader();
  PW_TRY(name_reader.status());

  if (name_reader.interval_size() > name_buf.size()) {
    return Status::OutOfRange();
  }

  Result<ByteSpan> read_result = name_reader.Read(name_buf);
  PW_TRY(read_result.status());

  const ConstByteSpan name_span = read_result.value();
  const std::string_view name_view(
      reinterpret_cast<const char*>(name_span.data()), name_span.size_bytes());

  return GetTargetFile(name_view);
}

protobuf::Message ManifestAccessor::GetTargetFile(std::string_view name) {
  PW_TRY(status());

  for (protobuf::Message target_file : GetTargetFiles()) {
    protobuf::String target_name = target_file.AsString(
        static_cast<uint32_t>(TargetFile::Fields::FILE_NAME));
    Result<bool> compare_result = target_name.Equal(name);
    PW_TRY(compare_result.status());
    if (compare_result.value()) {
      return target_file;
    }
  }

  return Status::NotFound();
}

}  // namespace pw::software_update
