// 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 "bios_setting.hpp"
#include "commands.hpp"
#include "helper.hpp"

#include <stdplus/gtest/tmp.hpp>

#include <fstream>
#include <ios>
#include <iostream>
#include <string>
#include <vector>

#include <gtest/gtest.h>

namespace google
{
namespace ipmi
{

using testing::_;
using ::testing::ElementsAre;

class BiosSettingTest : public stdplus::gtest::TestWithTmp
{
  public:
    std::string filename = std::format("{}/oem_bios_setting", CaseTmpDir());

    void writeTmpFile(std::vector<uint8_t> payload)
    {
        std::ofstream ofs;
        ofs.open(filename, std::ios::trunc | std::ios::binary);
        ofs.write(reinterpret_cast<char*>(payload.data()), payload.size());
        ofs.close();
    }
};

TEST_F(BiosSettingTest, NoOrEmptyFileRead)
{
    std::vector<uint8_t> request = {};

    HandlerMock hMock;
    EXPECT_EQ(::ipmi::responseRetBytesUnavailable(),
              readBiosSetting(request, &hMock));

    // Create an empty file
    writeTmpFile({});
    EXPECT_EQ(::ipmi::responseRetBytesUnavailable(),
              readBiosSetting(request, &hMock, filename));
    std::remove(filename.c_str());
}

TEST_F(BiosSettingTest, SuccessfulRead)
{
    std::vector<uint8_t> request = {};
    // Ensure 0x0A which is a new line character '\n', is read properly
    std::vector<uint8_t> payload = {0x0A, 0xDE, 0xAD, 0xBE, 0xEF, 0x0A};
    std::vector<uint8_t> expectedReply = {6,    0x0A, 0xDE, 0xAD,
                                          0xBE, 0xEF, 0x0A};

    writeTmpFile(payload);

    HandlerMock hMock;
    auto reply = readBiosSetting(request, &hMock, filename);
    auto result = ValidateReply(reply);
    auto& data = result.second;

    EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
    EXPECT_EQ(expectedReply.size() - 1, data.front());
    EXPECT_EQ(expectedReply, data);
    std::remove(filename.c_str());
}

TEST_F(BiosSettingTest, InvalidRequestWrite)
{
    // Empty request
    std::vector<uint8_t> request = {};

    HandlerMock hMock;
    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
              writeBiosSetting(request, &hMock));

    // Request with payload size 1 but no payload
    request = {0x01};
    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
              writeBiosSetting(request, &hMock));

    // Request with payload size 1 but actual payload size of 2 bytes
    request = {0x01, 0x02, 0x03};
    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
              writeBiosSetting(request, &hMock));

    // Request with payload size 2 but actual payload of 1 byte
    request = {0x02, 0x02};
    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
              writeBiosSetting(request, &hMock));
}

TEST_F(BiosSettingTest, SuccessfulWrite)
{
    std::vector<uint8_t> request = {0x02, 0xDE, 0xAD};

    // Write a dummy file to get around permission issues with CI
    // (Not needed in local CI)
    writeTmpFile({});
    HandlerMock hMock;
    auto reply = writeBiosSetting(request, &hMock, filename);
    auto result = ValidateReply(reply);
    auto& data = result.second;

    EXPECT_EQ(SysOEMCommands::SysWriteBiosSetting, result.first);
    EXPECT_EQ(std::vector<uint8_t>{2}, data);

    // Validate the payload is correct
    reply = readBiosSetting(request, &hMock, filename);
    result = ValidateReply(reply);
    data = result.second;

    EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
    EXPECT_EQ(request.size() - 1, data.front());
    EXPECT_EQ(request, data);

    // Verify that we can write a shorter string and it'll replace the original
    // content of the file
    request = {0x01, 0x0A};

    reply = writeBiosSetting(request, &hMock, filename);
    result = ValidateReply(reply);
    data = result.second;

    EXPECT_EQ(SysOEMCommands::SysWriteBiosSetting, result.first);
    EXPECT_EQ(std::vector<uint8_t>{1}, data);

    // Validate the payload is correct
    reply = readBiosSetting(request, &hMock, filename);
    result = ValidateReply(reply);
    data = result.second;

    EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
    EXPECT_EQ(request.size() - 1, data.front());
    EXPECT_EQ(request, data);
    // Cleanup the settings file
    std::remove(filename.c_str());
}

} // namespace ipmi
} // namespace google
