//
// Copyright (C) 2020 The Android Open Source Project
//
// 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
//
//      http://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 "update_engine/payload_generator/cow_size_estimator.h"

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include <android-base/unique_fd.h>
#include <libsnapshot/cow_writer.h>
#include <libsnapshot/cow_format.h>

#include "update_engine/payload_consumer/block_extent_writer.h"
#include "update_engine/payload_consumer/snapshot_extent_writer.h"
#include "update_engine/payload_consumer/xor_extent_writer.h"
#include "update_engine/common/utils.h"
#include "update_engine/payload_consumer/vabc_partition_writer.h"
#include "update_engine/payload_generator/extent_ranges.h"
#include "update_engine/payload_generator/extent_utils.h"
#include "update_engine/update_metadata.pb.h"

namespace chromeos_update_engine {
using android::snapshot::CreateCowEstimator;
using android::snapshot::ICowWriter;
// Compute XOR map, a map from dst extent to corresponding merge operation
static ExtentMap<const CowMergeOperation*, ExtentLess> ComputeXorMap(
    const google::protobuf::RepeatedPtrField<CowMergeOperation>& merge_ops) {
  ExtentMap<const CowMergeOperation*, ExtentLess> xor_map;
  for (const auto& merge_op : merge_ops) {
    if (merge_op.type() == CowMergeOperation::COW_XOR) {
      xor_map.AddExtent(merge_op.dst_extent(), &merge_op);
    }
  }
  return xor_map;
}

bool CowDryRun(
    FileDescriptorPtr source_fd,
    FileDescriptorPtr target_fd,
    const google::protobuf::RepeatedPtrField<InstallOperation>& operations,
    const google::protobuf::RepeatedPtrField<CowMergeOperation>&
        merge_operations,
    const size_t block_size,
    android::snapshot::ICowWriter* cow_writer,
    const size_t partition_size,
    const bool xor_enabled) {
  CHECK_NE(target_fd, nullptr);
  CHECK(target_fd->IsOpen());
  VABCPartitionWriter::WriteMergeSequence(merge_operations, cow_writer);
  ExtentRanges visited;
  SnapshotExtentWriter extent_writer(cow_writer);
  ExtentMap<const CowMergeOperation*, ExtentLess> xor_map =
      ComputeXorMap(merge_operations);
  ExtentRanges copy_blocks;
  for (const auto& cow_op : merge_operations) {
    if (cow_op.type() != CowMergeOperation::COW_COPY) {
      continue;
    }
    copy_blocks.AddExtent(cow_op.dst_extent());
  }
  for (const auto& op : operations) {
    switch (op.type()) {
      case InstallOperation::SOURCE_BSDIFF:
      case InstallOperation::BROTLI_BSDIFF:
      case InstallOperation::PUFFDIFF:
      case InstallOperation::ZUCCHINI:
      case InstallOperation::LZ4DIFF_PUFFDIFF:
      case InstallOperation::LZ4DIFF_BSDIFF: {
        if (xor_enabled) {
          std::unique_ptr<XORExtentWriter> writer =
              std::make_unique<XORExtentWriter>(
                  op, source_fd, cow_writer, xor_map, partition_size);
          TEST_AND_RETURN_FALSE(writer->Init(op.dst_extents(), block_size));
          for (const auto& ext : op.dst_extents()) {
            visited.AddExtent(ext);
            ssize_t bytes_read = 0;
            std::vector<unsigned char> new_data(ext.num_blocks() * block_size);
            if (!utils::PReadAll(target_fd,
                                 new_data.data(),
                                 new_data.size(),
                                 ext.start_block() * block_size,
                                 &bytes_read)) {
              PLOG(ERROR) << "Failed to read target data at " << ext;
              return false;
            }
            writer->Write(new_data.data(), ext.num_blocks() * block_size);
          }
          cow_writer->AddLabel(0);
          break;
        }
        [[fallthrough]];
      }
      case InstallOperation::REPLACE:
      case InstallOperation::REPLACE_BZ:
      case InstallOperation::REPLACE_XZ: {
        TEST_AND_RETURN_FALSE(extent_writer.Init(op.dst_extents(), block_size));
        for (const auto& ext : op.dst_extents()) {
          visited.AddExtent(ext);
          std::vector<unsigned char> data(ext.num_blocks() * block_size);
          ssize_t bytes_read = 0;
          if (!utils::PReadAll(target_fd,
                               data.data(),
                               data.size(),
                               ext.start_block() * block_size,
                               &bytes_read)) {
            PLOG(ERROR) << "Failed to read new block data at " << ext;
            return false;
          }
          extent_writer.Write(data.data(), data.size());
        }
        cow_writer->AddLabel(0);
        break;
      }
      case InstallOperation::ZERO:
      case InstallOperation::DISCARD: {
        for (const auto& ext : op.dst_extents()) {
          visited.AddExtent(ext);
          cow_writer->AddZeroBlocks(ext.start_block(), ext.num_blocks());
        }
        cow_writer->AddLabel(0);
        break;
      }
      case InstallOperation::SOURCE_COPY: {
        for (const auto& ext : op.dst_extents()) {
          visited.AddExtent(ext);
        }
        if (!VABCPartitionWriter::ProcessSourceCopyOperation(
                op, block_size, copy_blocks, source_fd, cow_writer, true)) {
          LOG(ERROR) << "Failed to process source copy operation: " << op.type()
                     << "\nsource extents: " << op.src_extents()
                     << "\ndestination extents: " << op.dst_extents();
          return false;
        }
        break;
      }
      default:
        LOG(ERROR) << "unknown op: " << op.type();
    }
  }

  const size_t last_block = partition_size / block_size;
  const auto unvisited_extents =
      FilterExtentRanges({ExtentForRange(0, last_block)}, visited);
  for (const auto& ext : unvisited_extents) {
    std::vector<unsigned char> data(ext.num_blocks() * block_size);
    ssize_t bytes_read = 0;
    if (!utils::PReadAll(target_fd,
                         data.data(),
                         data.size(),
                         ext.start_block() * block_size,
                         &bytes_read)) {
      PLOG(ERROR) << "Failed to read new block data at " << ext;
      return false;
    }
    auto to_write = data.size();
    // FEC data written on device is chunked to 1mb. We want to mirror that here
    while (to_write) {
      auto curr_write = std::min(block_size, to_write);
      cow_writer->AddRawBlocks(
          ext.start_block() + ((data.size() - to_write) / block_size),
          data.data() + (data.size() - to_write),
          curr_write);
      to_write -= curr_write;
    }
    CHECK_EQ(to_write, 0ULL);
    cow_writer->AddLabel(0);
  }

  TEST_AND_RETURN_FALSE(cow_writer->Finalize());

  return true;
}

android::snapshot::CowSizeInfo EstimateCowSizeInfo(
    FileDescriptorPtr source_fd,
    FileDescriptorPtr target_fd,
    const google::protobuf::RepeatedPtrField<InstallOperation>& operations,
    const google::protobuf::RepeatedPtrField<CowMergeOperation>&
        merge_operations,
    const size_t block_size,
    std::string compression,
    const size_t partition_size,
    const bool xor_enabled,
    uint32_t cow_version,
    uint64_t compression_factor) {
  android::snapshot::CowOptions options{
      .block_size = static_cast<uint32_t>(block_size),
      .compression = std::move(compression),
      .max_blocks = (partition_size / block_size),
      .compression_factor = compression_factor};
  auto cow_writer = CreateCowEstimator(cow_version, options);
  CHECK_NE(cow_writer, nullptr) << "Could not create cow estimator";
  CHECK(CowDryRun(source_fd,
                  target_fd,
                  operations,
                  merge_operations,
                  block_size,
                  cow_writer.get(),
                  partition_size,
                  xor_enabled));
  return cow_writer->GetCowSizeInfo();
}

}  // namespace chromeos_update_engine
