// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_STORAGE_FVM_SPARSE_READER_H_
#define SRC_STORAGE_FVM_SPARSE_READER_H_

#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>

#include <fbl/unique_fd.h>
#include <lz4/lz4frame.h>

#include "src/storage/fvm/fvm_sparse.h"

#ifdef __Fuchsia__
#include <zircon/syscalls.h>
#endif

#define LZ4_MAX_BLOCK_SIZE 65536

namespace fvm {

namespace internal {
// Helper struct for providing information about the buffer state.
struct BufferInfo {
  // Offset into buffer where valid data begins
  size_t offset;

  // Actual size of data contained within buffer
  size_t size;
};

// Internal class for representing read and write buffers for the sparse image.
class Buffer final {
 public:
  Buffer() noexcept = default;
  Buffer(uint64_t offset, size_t size, uint64_t capacity);
  Buffer(const Buffer&) = delete;
  Buffer(Buffer&&) noexcept = default;
  Buffer& operator=(const Buffer&) = delete;
  Buffer& operator=(Buffer&&) noexcept = default;
  ~Buffer() = default;

  // Write |length| bytes from |indata| into buffer.
  bool IsEmpty() const;

  // Writes |length| number of bytes from |data| into the buffer.
  void Write(uint8_t* data, size_t length);

  // Read up to |length| bytes from the buffer into |target|, setting |actual| to the total
  // amount of bytes copied.
  void Read(uint8_t* target, size_t length, size_t* actual);

  size_t size() const { return info_.size; }

  size_t capacity() const { return capacity_; }

  size_t offset() const { return info_.offset; }

  BufferInfo* info() { return &info_; }

  uint8_t* get() { return data_.get(); }

 private:
  // Data buffer
  std::unique_ptr<uint8_t[]> data_;

  // Maximum size allocated for buffer
  size_t capacity_;

  BufferInfo info_;
};

}  // namespace internal

class ReaderInterface {
 public:
  virtual zx_status_t Read(void* buf, size_t buf_size, size_t* size_actual) = 0;
  virtual ~ReaderInterface() = default;
};

class SparseReader {
 public:
  static zx_status_t Create(fbl::unique_fd fd, std::unique_ptr<SparseReader>* out);
  static zx_status_t CreateSilent(fbl::unique_fd fd, std::unique_ptr<SparseReader>* out);

  static zx_status_t Create(std::unique_ptr<ReaderInterface> reader,
                            std::unique_ptr<SparseReader>* out);

  ~SparseReader();

  fvm::SparseImage* Image();
  fvm::PartitionDescriptor* Partitions();

  // Read requested data from sparse file into buffer
  zx_status_t ReadData(uint8_t* data, size_t length, size_t* actual);
  // Write decompressed data into new file
  zx_status_t WriteDecompressed(fbl::unique_fd outfd);
  // A util function that reuses SparseReader logic to implement lz4 file decompression.
  static zx_status_t DecompressLZ4File(const char* in_file, const char* out_file);

 private:
  static zx_status_t CreateHelper(std::unique_ptr<ReaderInterface> reader, bool verbose,
                                  std::unique_ptr<SparseReader>* out);

  SparseReader(std::unique_ptr<ReaderInterface> reader, bool verbose);

  // Read in header data, prepare buffers and decompression context if necessary
  zx_status_t ReadMetadata();

  // Initialize buffer with a given |size|
  static zx_status_t InitializeBuffer(size_t size, internal::Buffer* out_buf);

  // Read |length| bytes of raw data from file directly into |data|. Return |actual| bytes read.
  zx_status_t ReadRaw(uint8_t* data, size_t length, size_t* actual);

  void PrintStats() const;

  zx_status_t SetupLZ4();

  // True if sparse file is compressed
  bool compressed_;

  // If true, all logs are printed.
  bool verbose_;

  std::unique_ptr<ReaderInterface> reader_;
  std::unique_ptr<uint8_t[]> metadata_;
  LZ4F_decompressionContext_t dctx_;

  size_t raw_bytes_read_ = 0;

  // A hint of the size of the next compressed frame to be decompressed.
  // May be an overestimate, but will not be an underestimate (0 indicates no more data left to
  // decompress).
  size_t to_read_;

  // Buffer for compressed data read directly from file
  internal::Buffer in_;
  // Buffer for decompressed data
  internal::Buffer out_;

#ifdef __Fuchsia__
  // Total time spent reading/decompressing data
  zx_ticks_t total_time_ = 0;
  // Total time spent reading data from fd
  zx_ticks_t read_time_ = 0;
#endif
};

}  // namespace fvm

#endif  // SRC_STORAGE_FVM_SPARSE_READER_H_
