/* SPDX-License-Identifier: Apache-2.0 */
/* Copyright (C) 2018 IBM Corp. */
#pragma once

extern "C" {
#include "backend.h"
#include "mboxd_pnor_partition_table.h"
};

#include "pnor_partition_table.hpp"

#include <fcntl.h>
#include <unistd.h>

#include <experimental/filesystem>
#include <string>

namespace openpower
{
namespace virtual_pnor
{

namespace fs = std::experimental::filesystem;

class Request
{
  public:
    /** @brief Construct a flash access request
     *
     *  @param[in] backend - The backend context used to process the request
     *  @param[in] offset - The absolute offset into the flash device as
     *                      provided by the mbox message associated with the
     *                      request
     *
     *  The class does not take ownership of the ctx pointer. The lifetime of
     *  the ctx pointer must strictly exceed the lifetime of the class
     *  instance.
     */
    Request(struct backend* backend, size_t offset) :
        backend(backend), partition(((struct vpnor_data*)backend->priv)
                                        ->vpnor->table->partition(offset)),
        base(partition.data.base << backend->block_size_shift),
        offset(offset - base)
    {
    }
    Request(const Request&) = delete;
    Request& operator=(const Request&) = delete;
    Request(Request&&) = default;
    Request& operator=(Request&&) = default;
    ~Request() = default;

    ssize_t read(void* dst, size_t len)
    {
        len = clamp(len);
        constexpr auto flags = O_RDONLY;
        fs::path path = getPartitionFilePath(flags);
        return fulfil(path, flags, dst, len);
    }

    ssize_t write(void* dst, size_t len)
    {
        if (len != clamp(len))
        {
            std::stringstream err;
            err << "Request size 0x" << std::hex << len << " from offset 0x"
                << std::hex << offset << " exceeds the partition size 0x"
                << std::hex
                << (partition.data.size << backend->block_size_shift);
            throw OutOfBoundsOffset(err.str());
        }
        constexpr auto flags = O_RDWR;
        /* Ensure file is at least the size of the maximum access */
        fs::path path = getPartitionFilePath(flags);
        resize(path, len);
        return fulfil(path, flags, dst, len);
    }

  private:
    /** @brief Clamp the access length to the maximum supported by the ToC */
    size_t clamp(size_t len);

    /** @brief Ensure the backing file is sized appropriately for the access
     *
     *  We need to ensure the file is big enough to satisfy the request so that
     *  mmap() will succeed for the required size.
     *
     *  @return The valid access length
     *
     *  Throws: std::system_error
     */
    void resize(const std::experimental::filesystem::path& path, size_t len);

    /** @brief Returns the partition file path associated with the offset.
     *
     *  The search strategy for the partition file depends on the value of the
     *  flags parameter.
     *
     *  For the O_RDONLY case:
     *
     *  1.  Depending on the partition type,tries to open the file
     *      from the associated partition(RW/PRSV/RO).
     *  1a. if file not found in the corresponding
     *      partition(RW/PRSV/RO) then tries to read the file from
     *      the read only partition.
     *  1b. if the file not found in the read only partition then
     *      throw exception.
     *
     * For the O_RDWR case:
     *
     *  1.  Depending on the partition type tries to open the file
     *      from the associated partition.
     *  1a. if file not found in the corresponding partition(RW/PRSV)
     *      then copy the file from the read only partition to the (RW/PRSV)
     *      partition depending on the partition type.
     *  1b. if the file not found in the read only partition then throw
     *      exception.
     *
     *  @param[in] flags - The flags that will be used to open the file. Must
     *                     be one of O_RDONLY or O_RDWR.
     *
     *  Post-condition: The file described by the returned path exists
     *
     *  Throws: std::filesystem_error, std::bad_alloc
     */
    std::experimental::filesystem::path getPartitionFilePath(int flags);

    /** @brief Fill dst with the content of the partition relative to offset.
     *
     *  @param[in] offset - The pnor offset(bytes).
     *  @param[out] dst - The buffer to fill with partition data
     *  @param[in] len - The length of the destination buffer
     */
    size_t fulfil(const std::experimental::filesystem::path& path, int flags,
                  void* dst, size_t len);

    struct backend* backend;
    const pnor_partition& partition;
    size_t base;
    size_t offset;
};

} // namespace virtual_pnor
} // namespace openpower
