// Copyright 2024 Google LLC
//
// 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 "mtd_util.hpp"

#include "fs.hpp"
#include "sys.hpp"

#include <fcntl.h>
#include <mtd/mtd-user.h>

#include <stdplus/print.hpp>

#include <algorithm>
#include <cstring>
#include <format>
#include <stdexcept>
#include <string>

namespace google
{
namespace hoth
{
namespace internal
{

// Sysfs directory containing info about mtd devices
auto constexpr sysfsMtd = "/sys/class/mtd";

std::string MtdImpl::findPartition(const std::string& name)
{
    auto dirs = listDir(sysfsMtd);

    for (const auto& p : dirs)
    {
        std::string line;

        try
        {
            line = getFirstLine(p / "name");
        }
        catch (const std::ios_base::failure& e)
        {
            // If we fail to read a name, just try the next one
            continue;
        }

        if (line == name)
        {
            return p.root_path() / "dev" / p.filename();
        }
    }

    throw std::runtime_error(
        std::format("Unable to find partition with name \"{}\"", name));
}

// TODO: choose the best block size
constexpr size_t blockSize = 4ULL * 1024;

void MtdImpl::flashCopy(const Sys* sys, const std::vector<uint8_t>& data,
                        const std::string& device)
{
    int fd = sys->open(device.c_str(), O_RDWR | O_SYNC);

    stdplus::print(stdout, "Opening device {}\n", device);
    if (fd < 0)
    {
        throw errnoException(std::format("Failed to open device {}", device));
    }

    mtd_info_t mtd;
    stdplus::print(stdout, "Getting device info\n");
    if (sys->ioctl(fd, MEMGETINFO, &mtd) < 0)
    {
        sys->close(fd);

        throw errnoException(std::format("Failed to get info on {}", device));
    }
    stdplus::print(stdout, "Data size: {}, MTD size: {}\n", data.size(),
                   mtd.size);

    if (data.size() > mtd.size)
    {
        sys->close(fd);

        throw std::runtime_error(std::format(
            "Data size {} too large for device {}", data.size(), device));
    }

    erase_info_t erase;
    erase.start = 0;
    erase.length = mtd.size;
    stdplus::print(stdout, "Erasing data block of length {}\n", mtd.size);
    if (sys->ioctl(fd, MEMERASE, &erase) < 0)
    {
        sys->close(fd);

        throw errnoException(
            std::format("Failed to erase mtd device {}", device));
    }

    stdplus::print(stdout, "Sending data with max block size {}\n", blockSize);
    size_t count = 0;
    while (count < data.size())
    {
        size_t writeSize = std::min(data.size() - count, blockSize);
        auto ret = sys->write(fd, data.data() + count, writeSize);

        if (ret < 0)
        {
            if (errno == EINTR)
            {
                continue; // interrupted; try again
            }
            sys->close(fd);

            throw errnoException(
                std::format("Failed to write to mtd device {}", device));
        }
        if (ret == 0)
        {
            sys->close(fd);

            throw std::runtime_error(std::format(
                "Unexpected EOF while writing to mtd device {}", device));
        } // ret > 0
        count += ret;
    }

    stdplus::print(stdout, "Validating data with max block size {}\n",
                   blockSize);
    // Validate written data
    std::vector<uint8_t> readBuffer(blockSize);

    // Reset the file descriptor offset back to 0 before reading
    sys->lseek(fd, 0, SEEK_SET);

    count = 0;
    while (count < data.size())
    {
        size_t readSize = std::min(data.size() - count, blockSize);
        auto ret = sys->read(fd, readBuffer.data(), readSize);

        if (ret < 0)
        {
            if (errno == EINTR)
            {
                continue; // interrupted; try again
            }
            sys->close(fd);

            throw errnoException(
                std::format("Failed to read from mtd device {}", device));
        }
        if (ret == 0)
        {
            sys->close(fd);

            throw std::runtime_error(std::format(
                "Unexpected EOF while reading from mtd device {}", device));
        } // ret > 0
        int rc = std::memcmp(data.data() + count, readBuffer.data(), ret);
        if (rc != 0)
        {
            sys->close(fd);

            throw std::runtime_error(std::format(
                "Written data failed validation at {} bytes", count));
        }
        count += ret;
    }

    stdplus::print(stdout, "Closing device {}\n", device);
    auto retClose = sys->close(fd);
    if (retClose < 0)
    {
        throw errnoException(std::format("Failed to close device {}", device));
    }
}

MtdImpl mtdImpl;

} // namespace internal

} // namespace hoth

} // namespace google
