/*
 * Copyright (C) 2016 Intel Corporation. All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "test_va_api_fixture.h"

#include <algorithm>
#include <functional>

#include <fcntl.h> // for O_RDWR
#include <limits>
#include <unistd.h> // for close()
#include <va/va_drm.h>

namespace VAAPI {

VAAPIFixture::VAAPIFixture()
    : ::testing::Test::Test()
    , m_vaDisplay(NULL)
    , m_restoreDriverName(getenv("LIBVA_DRIVER_NAME"))
    , m_drmHandle(-1)
    , drmDevicePaths({ "/dev/dri/renderD128", "/dev/dri/card0" })
    , m_configID(VA_INVALID_ID)
    , m_contextID(VA_INVALID_ID)
    , m_bufferID(VA_INVALID_ID)
    , m_skip("")
{
    return;
}

VAAPIFixture::~VAAPIFixture()
{
    m_vaDisplay = NULL;
    if (m_drmHandle >= 0)
        close(m_drmHandle);
    m_drmHandle = -1;

    // Ensure LIBVA_DRIVER_NAME environment is restored to its original
    // setting so successive tests use the expected driver.
    unsetenv("LIBVA_DRIVER_NAME");
    if (m_restoreDriverName)
        setenv("LIBVA_DRIVER_NAME", m_restoreDriverName, 1);

    if (not m_skip.empty()) {
        EXPECT_FALSE(HasFailure())
            << "skip message is set, but something failed";
        if (not HasFailure()) {
            RecordProperty("skipped", true);
            std::cout << "[ SKIPPED ] " << m_skip << std::endl;
        }
    }
}

VADisplay VAAPIFixture::getDisplay()
{
    uint32_t i;

    for (i = 0; i < sizeof(drmDevicePaths) / sizeof(*drmDevicePaths); i++) {
        m_drmHandle = open(drmDevicePaths[i].c_str(), O_RDWR);
        if (m_drmHandle < 0)
            continue;
        m_vaDisplay = vaGetDisplayDRM(m_drmHandle);

        if (m_vaDisplay)
            return m_vaDisplay;
    }

    return NULL;
}

VADisplay VAAPIFixture::doInitialize()
{
    VADisplay vaDisplay;
    VAStatus status;
    int majorVersion, minorVersion;

    vaDisplay = getDisplay();
    EXPECT_TRUE(vaDisplay);
    if (!vaDisplay) {
        return NULL;
    }

    status = vaInitialize(vaDisplay, &majorVersion, &minorVersion);
    EXPECT_STATUS(status) << "failed to initialize vaapi";
    if (status != VA_STATUS_SUCCESS) {
        return NULL;
    }

    return vaDisplay;
}

void VAAPIFixture::queryConfigProfiles(Profiles& profiles) const
{
    const int maxProfiles = vaMaxNumProfiles(m_vaDisplay);
    ASSERT_GT(maxProfiles, 0);
    profiles.resize(maxProfiles);

    int numProfiles(0);
    EXPECT_STATUS(
        vaQueryConfigProfiles(m_vaDisplay, profiles.data(), &numProfiles));

    if (not HasFailure()) {
        ASSERT_LE(numProfiles, maxProfiles);
        ASSERT_GT(numProfiles, 0);
        profiles.resize(numProfiles);
    } else {
        profiles.clear();
    }
}

void VAAPIFixture::queryConfigEntrypoints(const VAProfile& profile,
    Entrypoints& entrypoints, const VAStatus& expectation) const
{
    const int maxEntrypoints = vaMaxNumEntrypoints(m_vaDisplay);
    ASSERT_GT(maxEntrypoints, 0);
    entrypoints.resize(maxEntrypoints);

    int numEntrypoints(0);
    EXPECT_STATUS_EQ(
        expectation,
        vaQueryConfigEntrypoints(m_vaDisplay, profile, entrypoints.data(),
            &numEntrypoints));

    if ((VA_STATUS_SUCCESS == expectation) and not HasFailure()) {
        ASSERT_LE(numEntrypoints, maxEntrypoints);
        ASSERT_GT(numEntrypoints, 0);
        entrypoints.resize(numEntrypoints);
    } else {
        entrypoints.clear();
    }
}

VAStatus VAAPIFixture::getSupportStatus(const VAProfile& profile,
    const VAEntrypoint& entrypoint) const
{
    Profiles profiles;
    queryConfigProfiles(profiles);

    const auto pBegin(profiles.begin());
    const auto pEnd(profiles.end());
    if (std::find(pBegin, pEnd, profile) != pEnd) {
        Entrypoints entrypoints;
        queryConfigEntrypoints(profile, entrypoints);

        const auto eBegin(entrypoints.begin());
        const auto eEnd(entrypoints.end());
        return (std::find(eBegin, eEnd, entrypoint) != eEnd) ?
            VA_STATUS_SUCCESS : VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
    }

    return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
}

bool VAAPIFixture::isSupported(const VAProfile& profile,
    const VAEntrypoint& entrypoint) const
{
    return VA_STATUS_SUCCESS == getSupportStatus(profile, entrypoint);
}

void VAAPIFixture::getConfigAttributes(const VAProfile& profile,
    const VAEntrypoint& entrypoint, ConfigAttributes& attribs,
    const VAStatus& expectation) const
{
    const bool defaults(attribs.empty());

    if (defaults) {
        // fill config attributes with default config attributes
        const auto op = [](const VAConfigAttribType& t) {
            return VAConfigAttrib{type: t, value: VA_ATTRIB_NOT_SUPPORTED};
        };
        std::transform(g_vaConfigAttribTypes.begin(),
            g_vaConfigAttribTypes.end(), std::back_inserter(attribs), op);
    }

    ASSERT_FALSE(attribs.empty());

    EXPECT_STATUS_EQ(
        expectation,
        vaGetConfigAttributes(
            m_vaDisplay, profile, entrypoint, attribs.data(), attribs.size()));

    if (defaults) {
        // remove unsupported config attributes
        const auto begin(attribs.begin());
        const auto end(attribs.end());
        const auto predicate = [](const VAConfigAttrib& a) {
            return a.value == VA_ATTRIB_NOT_SUPPORTED;
        };
        attribs.erase(std::remove_if(begin, end, predicate), end);
    }
}

void VAAPIFixture::createConfig(const VAProfile& profile,
    const VAEntrypoint& entrypoint, const ConfigAttributes& attribs,
    const VAStatus& expectation)
{
    ASSERT_INVALID_ID(m_configID)
        << "test logic error: did you forget to call destroyConfig?";

    EXPECT_STATUS_EQ(
        expectation,
        vaCreateConfig(m_vaDisplay, profile, entrypoint,
            (attribs.size() != 0 ?
                const_cast<VAConfigAttrib*>(attribs.data()) : NULL),
            attribs.size(), &m_configID))
        << "profile    = " << profile << std::endl
        << "entrypoint = " << entrypoint << std::endl
        << "numAttribs = " << attribs.size();

    if (expectation == VA_STATUS_SUCCESS) {
        EXPECT_ID(m_configID);
    } else {
        EXPECT_INVALID_ID(m_configID);
    }
}

void VAAPIFixture::queryConfigAttributes(
    const VAProfile& expectedProfile, const VAEntrypoint& expectedEntrypoint,
    ConfigAttributes& attributes, const VAStatus& expectedStatus) const
{
    VAProfile actualProfile;
    VAEntrypoint actualEntrypoint;
    int numAttributes(0);

    ASSERT_TRUE(attributes.empty())
        << "test logic error: attributes must be empty";

    const int maxAttributes = vaMaxNumConfigAttributes(m_vaDisplay);

    ASSERT_GT(maxAttributes, 0);

    attributes.resize(maxAttributes);

    EXPECT_STATUS_EQ(
        expectedStatus,
        vaQueryConfigAttributes(m_vaDisplay, m_configID, &actualProfile,
            &actualEntrypoint, attributes.data(), &numAttributes));

    if (expectedStatus == VA_STATUS_SUCCESS) {
        EXPECT_EQ(expectedProfile, actualProfile);
        EXPECT_EQ(expectedEntrypoint, actualEntrypoint);
        ASSERT_LE(numAttributes, maxAttributes);
        ASSERT_GT(numAttributes, 0);

        attributes.resize(numAttributes);

        // reported config attributes should be supported
        for (const auto& attribute : attributes) {
            EXPECT_NE(VA_ATTRIB_NOT_SUPPORTED, attribute.value);
        }
    } else {
        attributes.clear();
    }
}

void VAAPIFixture::destroyConfig(const VAStatus& expectation)
{
    EXPECT_STATUS_EQ(expectation, vaDestroyConfig(m_vaDisplay, m_configID));
    m_configID = VA_INVALID_ID;
}

void VAAPIFixture::querySurfaceAttributes(SurfaceAttributes& attribs) const
{
    ASSERT_TRUE(attribs.empty())
        << "test logic error: surface attributes must be empty";

    unsigned numAttribs(0);

    ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID, NULL,
        &numAttribs));

    ASSERT_GT(numAttribs, 0u);

    attribs.resize(numAttribs);

    ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
        attribs.data(), &numAttribs));

    ASSERT_GT(numAttribs, 0u);
    EXPECT_GE(attribs.size(), numAttribs);

    attribs.resize(numAttribs);

    const uint32_t flags = 0x0 | VA_SURFACE_ATTRIB_GETTABLE
        | VA_SURFACE_ATTRIB_SETTABLE;

    for (const auto& attrib : attribs) {
        EXPECT_NE(attrib.flags & flags,
            (uint32_t)VA_SURFACE_ATTRIB_NOT_SUPPORTED);
        EXPECT_GE(attrib.value.type, VAGenericValueTypeInteger);
        EXPECT_LE(attrib.value.type, VAGenericValueTypeFunc);
    }
}

void VAAPIFixture::getMinMaxSurfaceResolution(
    Resolution& minRes, Resolution& maxRes) const
{
    const Resolution::DataType maxVal =
        std::numeric_limits<Resolution::DataType>::max();

    // set default resolutions
    minRes.width = 1;
    minRes.height = 1;
    maxRes.width = maxVal;
    maxRes.height = maxVal;

    SurfaceAttributes attribs;
    querySurfaceAttributes(attribs);

    SurfaceAttributes::const_iterator match;
    const SurfaceAttributes::const_iterator begin(attribs.begin());
    const SurfaceAttributes::const_iterator end(attribs.end());

    // minimum surface width
    match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
        {return a.type == VASurfaceAttribMinWidth;});
    if (match != end) {
        EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
        ASSERT_GE(match->value.value.i, 1);
        ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
        minRes.width = match->value.value.i;
    }

    // minimum surface height
    match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
        {return a.type == VASurfaceAttribMinHeight;});
    if (match != end) {
        EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
        ASSERT_GE(match->value.value.i, 1);
        ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
        minRes.height = match->value.value.i;
    }

    // maximum surface width
    match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
        {return a.type == VASurfaceAttribMaxWidth;});
    if (match != end) {
        EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
        ASSERT_GE(match->value.value.i, 1);
        ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
        maxRes.width = match->value.value.i;
    }

    // maximum surface height
    match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
        {return a.type == VASurfaceAttribMaxHeight;});
    if (match != end) {
        EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
        ASSERT_GE(match->value.value.i, 1);
        ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
        maxRes.height = match->value.value.i;
    }

    EXPECT_LE(minRes, maxRes);
}

void VAAPIFixture::createSurfaces(Surfaces& surfaces, const unsigned format,
    const Resolution& resolution, const SurfaceAttributes& attribs,
    const VAStatus& expectation) const
{
    ASSERT_GT(surfaces.size(), 0u)
        << "test logic error: surfaces must not be emtpy";
    for (const auto& surface : surfaces) {
        ASSERT_INVALID_ID(surface)
            << "test logic error: surfaces must all be VA_INVALID_SURFACE";
    }

    ASSERT_STATUS_EQ(
        expectation,
        vaCreateSurfaces(m_vaDisplay, format, resolution.width,
            resolution.height, surfaces.data(), surfaces.size(),
            (attribs.size() != 0 ?
                const_cast<VASurfaceAttrib*>(attribs.data()) : NULL),
            attribs.size()));

    if (expectation == VA_STATUS_SUCCESS) {
        for (const auto& surface : surfaces) {
            ASSERT_ID(surface);
        }
    }
}

void VAAPIFixture::destroySurfaces(Surfaces& surfaces) const
{
    if (surfaces.size() != 0) {
        EXPECT_STATUS(vaDestroySurfaces(m_vaDisplay, surfaces.data(),
            surfaces.size()));
    }
}

void VAAPIFixture::createBuffer(const VABufferType& bufferType,
    const size_t bufferSize, const VAStatus& expectation)
{
    ASSERT_INVALID_ID(m_bufferID)
        << "test logic error: did you forget to call destroyBuffer?";

    EXPECT_STATUS_EQ(
        expectation,
        vaCreateBuffer(m_vaDisplay, m_contextID, bufferType, bufferSize,
            1, NULL, &m_bufferID));
}

void VAAPIFixture::destroyBuffer(const VAStatus& expectation)
{
    EXPECT_STATUS_EQ(expectation, vaDestroyBuffer(m_vaDisplay, m_bufferID));
    m_bufferID = VA_INVALID_ID;
}

void VAAPIFixture::doCreateContext(const Resolution& resolution,
    const VAStatus& expectation)
{
    m_contextID = 0;
    ASSERT_STATUS_EQ(expectation,
                     vaCreateContext(m_vaDisplay, m_configID, resolution.width,
                                     resolution.height, VA_PROGRESSIVE,
                                     NULL, 0, &m_contextID));
}

void VAAPIFixture::doDestroyContext(const VAStatus& expectation)
{
    ASSERT_STATUS_EQ(expectation, vaDestroyContext(m_vaDisplay, m_contextID));
}

void VAAPIFixture::doTerminate()
{
    EXPECT_STATUS(vaTerminate(m_vaDisplay));
}

void VAAPIFixture::skipTest(const std::string& message)
{
    ASSERT_FALSE(message.empty())
        << "test logic error: skip message cannot be empty";
    ASSERT_TRUE(m_skip.empty())
        << "test logic error: test already marked as skipped";

    m_skip = message;
}

void VAAPIFixture::skipTest(const VAProfile& profile,
    const VAEntrypoint& entrypoint)
{
    std::ostringstream oss;
    oss << profile << " / " << entrypoint << " not supported on this hardware";
    skipTest(oss.str());
}

TEST_F(VAAPIFixture, getDisplay)
{
    VADisplay vaDisplay;

    vaDisplay = getDisplay();
    ASSERT_TRUE(vaDisplay);
    EXPECT_STATUS(vaTerminate(vaDisplay));
}

} // namespace VAAPI
