#include <sdbusplus/bus.hpp>
#include <gtest/gtest.h>

#include "host_epoch.hpp"
#include "config.h"
#include "types.hpp"

namespace phosphor
{
namespace time
{

using namespace std::chrono;
using namespace std::chrono_literals;

class TestHostEpoch : public testing::Test
{
    public:
        sdbusplus::bus::bus bus;
        HostEpoch hostEpoch;

        static constexpr auto FILE_NOT_EXIST = "path/to/file-not-exist";
        static constexpr auto FILE_OFFSET = "saved_host_offset";
        static constexpr auto delta = 2s;

        TestHostEpoch()
            : bus(sdbusplus::bus::new_default()),
              hostEpoch(bus, OBJPATH_HOST)
        {
            // Make sure the file does not exist
            std::remove(FILE_NOT_EXIST);
        }
        ~TestHostEpoch()
        {
            // Cleanup test file
            std::remove(FILE_OFFSET);
        }

        // Proxies for HostEpoch's private members and functions
        Mode getTimeMode()
        {
            return hostEpoch.timeMode;
        }
        Owner getTimeOwner()
        {
            return hostEpoch.timeOwner;
        }
        template <typename T>
        T readData(const char* fileName)
        {
            return HostEpoch::readData<T>(fileName);
        }
        template <typename T>
        void writeData(const char* fileName, T&& data)
        {
            HostEpoch::writeData<T>(fileName, std::forward<T>(data));
        }
        microseconds getOffset()
        {
            return hostEpoch.offset;
        }
        void setTimeOwner(Owner owner)
        {
            hostEpoch.timeOwner = owner;
        }
};

TEST_F(TestHostEpoch, empty)
{
    EXPECT_EQ(Mode::NTP, getTimeMode());
    EXPECT_EQ(Owner::BMC, getTimeOwner());
}

TEST_F(TestHostEpoch, readDataFileNotExist)
{
    // When file does not exist, the default offset shall be 0
    microseconds offset(0);
    auto value = readData<decltype(offset)::rep>(FILE_NOT_EXIST);
    EXPECT_EQ(0, value);
}

TEST_F(TestHostEpoch, writeAndReadData)
{
    // Write offset to file
    microseconds offsetToWrite(1234567);
    writeData<decltype(offsetToWrite)::rep>(FILE_OFFSET, offsetToWrite.count());

    // Read it back
    microseconds offsetToRead;
    offsetToRead = microseconds(
        readData<decltype(offsetToRead)::rep>(FILE_OFFSET));
    EXPECT_EQ(offsetToWrite, offsetToRead);
}

TEST_F(TestHostEpoch, setElapsedNotAllowed)
{
    // By default offset shall be 0
    EXPECT_EQ(0, getOffset().count());

    // Set time in BMC mode is not allowed,
    // so verify offset is still 0 after set time
    microseconds diff = 1min;
    hostEpoch.elapsed(hostEpoch.elapsed() + diff.count());
    EXPECT_EQ(0, getOffset().count());
}

TEST_F(TestHostEpoch, setElapsedInFutureAndGet)
{
    // Set to HOST owner so that we can set elapsed
    setTimeOwner(Owner::HOST);

    // Get current time, and set future +1min time
    auto t1 = hostEpoch.elapsed();
    EXPECT_NE(0, t1);
    microseconds diff = 1min;
    auto t2 = t1 + diff.count();
    hostEpoch.elapsed(t2);

    // Verify that the offset shall be positive,
    // and less or equal to diff, and shall be not too less.
    auto offset = getOffset();
    EXPECT_GT(offset, microseconds(0));
    EXPECT_LE(offset, diff);
    diff -= delta;
    EXPECT_GE(offset, diff);

    // Now get time shall be around future +1min time
    auto epochNow = duration_cast<microseconds>(
        system_clock::now().time_since_epoch()).count();
    auto elapsedGot = hostEpoch.elapsed();
    EXPECT_LT(epochNow, elapsedGot);
    auto epochDiff = elapsedGot - epochNow;
    diff = 1min;
    EXPECT_GT(epochDiff, (diff - delta).count());
    EXPECT_LT(epochDiff, (diff + delta).count());
}

TEST_F(TestHostEpoch, setElapsedInPastAndGet)
{
    // Set to HOST owner so that we can set elapsed
    setTimeOwner(Owner::HOST);

    // Get current time, and set past -1min time
    auto t1 = hostEpoch.elapsed();
    EXPECT_NE(0, t1);
    microseconds diff = 1min;
    auto t2 = t1 - diff.count();
    hostEpoch.elapsed(t2);

    // Verify that the offset shall be negative, and the absolute value
    // shall be equal or greater than diff, and shall not be too greater
    auto offset = getOffset();
    EXPECT_LT(offset, microseconds(0));
    offset = -offset;
    EXPECT_GE(offset, diff);
    diff += 10s;
    EXPECT_LE(offset, diff);

    // Now get time shall be around past -1min time
    auto epochNow = duration_cast<microseconds>(
        system_clock::now().time_since_epoch()).count();
    auto elapsedGot = hostEpoch.elapsed();
    EXPECT_LT(elapsedGot, epochNow);
    auto epochDiff = epochNow - elapsedGot;
    diff = 1min;
    EXPECT_GT(epochDiff, (diff - delta).count());
    EXPECT_LT(epochDiff, (diff + delta).count());
}

}
}
