#pragma once

#include <vector>
#include <memory>
#include <numeric>
#include <experimental/filesystem>
#include "pnor_partition_defs.h"

namespace openpower
{
namespace virtual_pnor
{

namespace fs = std::experimental::filesystem;

using PartitionTable = std::vector<uint8_t>;
using checksum_t = uint32_t;

/** @brief Convert the input partition table to big endian.
 *
 *  @param[in] src - reference to the pnor partition table
 *
 *  @returns converted partition table
 */
PartitionTable endianFixup(const PartitionTable& src);

/** @brief Parse a ToC line (entry) into the corresponding FFS partition
 * object.
 *
 * @param[in] line - The ToC line to parse
 * @param[in] blockSize - The flash block size in bytes
 * @param[out] part - The partition object to populate with the information
 *                    parsed from the provided ToC line
 *
 * @returns True on success, false on failure.
 */
bool parseTocLine(const std::string& line, size_t blockSize,
                  pnor_partition& part);

namespace details
{

/** @brief Compute XOR-based checksum, by XORing consecutive words
 *         in the input data. Input must be aligned to word boundary.
 *
 *  @param[in] data - input data on which checksum is computed
 *
 *  @returns computed checksum
 */
template <class T> checksum_t checksum(const T& data)
{
    static_assert(sizeof(decltype(data)) % sizeof(checksum_t) == 0,
                  "sizeof(data) is not aligned to sizeof(checksum_t) boundary");

    auto begin = reinterpret_cast<const checksum_t*>(&data);
    auto end = begin + (sizeof(decltype(data)) / sizeof(checksum_t));

    return std::accumulate(begin, end, 0, std::bit_xor<checksum_t>());
}

} // namespace details

namespace partition
{

/** @class Table
 *  @brief Generates virtual PNOR partition table.
 *
 *  Generates virtual PNOR partition table upon construction. Reads
 *  the PNOR information generated by this tool :
 *  github.com/openbmc/openpower-pnor-code-mgmt/blob/master/generate-squashfs,
 *  which generates a minimalistic table-of-contents (toc) file and
 *  individual files to represent various partitions that are of interest -
 *  these help form the "virtual" PNOR, which is typically a subset of the full
 *  PNOR image.
 *  These files are stored in a well-known location on the PNOR.
 *  Based on this information, this class prepares the partition table whose
 *  structure is as outlined in pnor_partition.h.
 *
 *  The virtual PNOR supports 4KB erase blocks - partitions must be aligned to
 *  this size.
 */
class Table
{
  public:
    /** @brief Constructor accepting the path of the directory
     *         that houses the PNOR partition files.
     *
     *  @param[in] directory - path of the directory housing PNOR partitions
     *  @param[in] blockSize - PNOR block size, in bytes. See
     *             open-power/hostboot/blob/master/src/usr/pnor/ffs.h for
     *             the PNOR FFS structure.
     *  @param[in] pnorSize - PNOR size, in bytes
     */
    Table(fs::path&& directory, size_t blockSize, size_t pnorSize);

    Table(const Table&) = delete;
    Table& operator=(const Table&) = delete;
    Table(Table&&) = delete;
    Table& operator=(Table&&) = delete;
    ~Table() = default;

    /** @brief Return size of partition table
     *
     *  @returns size_t - size of partition table in blocks
     */
    size_t size() const
    {
        return szBlocks;
    }

    /** @brief Return a partition table having byte-ordering
     *         that the host expects.
     *
     *  The host needs the partion table in big-endian.
     *
     *  @returns const reference to host partition table.
     */
    const pnor_partition_table& getHostTable() const
    {
        return *(reinterpret_cast<const pnor_partition_table*>(hostTbl.data()));
    }

    /** @brief Return a little-endian partition table
     *
     *  @returns const reference to native partition table
     */
    const pnor_partition_table& getNativeTable() const
    {
        return *(reinterpret_cast<const pnor_partition_table*>(tbl.data()));
    }

    /** @brief Return partition corresponding to PNOR offset, the offset
     *         is within returned partition.
     *
     *  @param[in] offset - PNOR offset in bytes
     *
     *  @returns const reference to pnor_partition, if found, else an
     *           exception will be thrown.
     */
    const pnor_partition& partition(size_t offset) const;

    /** @brief Return partition corresponding to input partition name.
     *
     *  @param[in] name - PNOR partition name
     *
     *  @returns const reference to pnor_partition, if found, else an
     *           exception will be thrown.
     */
    const pnor_partition& partition(const std::string& name) const;

  private:
    /** @brief Prepares a vector of PNOR partition structures.
     */
    void preparePartitions();

    /** @brief Prepares the PNOR header.
     */
    void prepareHeader();

    /** @brief Allocate memory to hold the partion table. Determine the
     *         amount needed based on the partition files in the toc file.
     *
     *  @param[in] tocFile - Table of contents file path.
     */
    void allocateMemory(const fs::path& tocFile);

    /** @brief Return a little-endian partition table
     *
     *  @returns reference to native partition table
     */
    pnor_partition_table& getNativeTable()
    {
        return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
    }

    /** @brief Size of the PNOR partition table -
     *         sizeof(pnor_partition_table) +
     *         (no. of partitions * sizeof(pnor_partition)),
     *         measured in erase-blocks.
     */
    size_t szBlocks;

    /** @brief Partition table */
    PartitionTable tbl;

    /** @brief Partition table with host byte ordering */
    PartitionTable hostTbl;

    /** @brief Directory housing generated PNOR partition files */
    fs::path directory;

    /** @brief Number of partitions */
    size_t numParts;

    /** @brief PNOR block size, in bytes */
    size_t blockSize;

    /** @brief PNOR size, in bytes */
    size_t pnorSize;
};

} // namespace partition
} // namespace virtual_pnor
} // namespace openpower
