/*
 * 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 <unistd.h> // for close()
#include <va/va_drm.h>

namespace VAAPI {

VAAPIFixture::VAAPIFixture()
    : ::testing::Test::Test()
    , m_vaDisplay(NULL)
    , m_drmHandle(-1)
    , drmDevicePaths({ "/dev/dri/renderD128", "/dev/dri/card0" })
    , m_maxEntrypoints(0)
    , m_maxProfiles(0)
    , m_numProfiles(0)
    , m_maxConfigAttributes(0)
    , m_configID(VA_INVALID_ID)
    , m_contextID(VA_INVALID_ID)
    , m_bufferID(VA_INVALID_ID)

{
    m_profileList.clear();
    m_entrypointList.clear();
    m_configAttribList.clear();
    m_configAttribToCreateConfig.clear();
    m_querySurfaceAttribList.clear();
    m_surfaceID.clear();
}

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

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 m_vaDisplay;
}

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

    vaDisplay = getDisplay();
    EXPECT_TRUE(vaDisplay);

    if (vaDisplay) {
        EXPECT_STATUS(vaInitialize(vaDisplay, &majorVersion, &minorVersion));
    }

    return vaDisplay;
}

void VAAPIFixture::doGetMaxProfiles()
{
    m_maxProfiles = vaMaxNumProfiles(m_vaDisplay);
    EXPECT_TRUE(m_maxProfiles > 0) << m_maxProfiles
                                   << " profiles are reported, check setup";
}

void VAAPIFixture::doGetMaxEntrypoints()
{
    m_maxEntrypoints = vaMaxNumEntrypoints(m_vaDisplay);
    EXPECT_TRUE(m_maxEntrypoints > 0)
        << m_maxEntrypoints << " entrypoints are reported, check setup";
}

void VAAPIFixture::doGetMaxNumConfigAttribs()
{
    m_maxConfigAttributes = vaMaxNumConfigAttributes(m_vaDisplay);

    EXPECT_EQ(m_maxConfigAttributes, 32);
}

void VAAPIFixture::doGetMaxValues()
{

    doGetMaxProfiles();
    doGetMaxEntrypoints();
    doGetMaxNumConfigAttribs();
}

void VAAPIFixture::doQueryConfigProfiles()
{
    m_profileList.resize(m_maxProfiles);

    ASSERT_STATUS(
        vaQueryConfigProfiles(m_vaDisplay, &m_profileList[0], &m_numProfiles));

    // at least one profile should be supported for tests to be executed
    ASSERT_TRUE(m_numProfiles > 0);

    m_profileList.resize(m_numProfiles);
}

std::vector<VAProfile> VAAPIFixture::getSupportedProfileList()
{
    return m_profileList;
}

std::vector<VAEntrypoint> VAAPIFixture::getSupportedEntrypointList()
{
    return m_entrypointList;
}

bool VAAPIFixture::doFindProfileInList(VAProfile profile)
{
    return std::find(m_profileList.begin(), m_profileList.end(), profile)
           != m_profileList.end();
}

void VAAPIFixture::doQueryConfigEntrypoints(VAProfile profile)
{
    int numEntrypoints = 0;

    m_entrypointList.resize(m_maxEntrypoints);
    ASSERT_STATUS(vaQueryConfigEntrypoints(
        m_vaDisplay, profile, &m_entrypointList[0], &numEntrypoints));

    EXPECT_TRUE(numEntrypoints > 0);

    m_entrypointList.resize(numEntrypoints);
}

bool VAAPIFixture::doFindEntrypointInList(VAEntrypoint entrypoint)
{
    return std::find(m_entrypointList.begin(), m_entrypointList.end(),
                     entrypoint)
           != m_entrypointList.end();
}

void VAAPIFixture::doFillConfigAttribList()
{
    m_configAttribList.clear();
    // fill it with all the VAConfigAttribs known
    for (auto& it : m_vaConfigAttribs) {
        VAConfigAttrib configAttrib;

        configAttrib.type = it;

        m_configAttribList.push_back(configAttrib);
    }

    EXPECT_EQ(m_configAttribList.size(), m_vaConfigAttribs.size());
}

void VAAPIFixture::doGetConfigAttributes(VAProfile profile,
                                         VAEntrypoint entrypoint)
{
    int numAttributes = m_configAttribList.size();
    ASSERT_STATUS(vaGetConfigAttributes(m_vaDisplay, profile, entrypoint,
                                        &m_configAttribList[0], numAttributes));
}

void VAAPIFixture::doGetConfigAttributes(
    VAProfile profile, VAEntrypoint entrypoint,
    std::vector<VAConfigAttrib>& configAttrib)
{
    int numAttributes = configAttrib.size();
    ASSERT_STATUS(vaGetConfigAttributes(m_vaDisplay, profile, entrypoint,
                                        &configAttrib[0], numAttributes));
}

const std::vector<VAConfigAttrib>& VAAPIFixture::getConfigAttribList() const
{
    return m_configAttribList;
}

const std::vector<VAConfigAttrib>&
VAAPIFixture::getQueryConfigAttribList() const
{
    return m_queryConfigAttribList;
}

void VAAPIFixture::doCheckAttribsMatch(std::vector<VAConfigAttrib> configAttrib)
{
    auto itOne = m_queryConfigAttribList.begin();
    auto itTwo = configAttrib.begin();
    auto diff = 0;

    EXPECT_EQ(configAttrib.size(), m_queryConfigAttribList.size());

    while (itOne != m_queryConfigAttribList.end()
           && itTwo != configAttrib.end()) {
        if (itOne->value != itTwo->value || itOne->type != itTwo->type) {
            diff++;
        }
        itOne++;
        itTwo++;
    }

    EXPECT_TRUE(diff == 0);
}

void VAAPIFixture::doCreateConfigWithAttrib(VAProfile profile,
                                            VAEntrypoint entrypoint)
{

    m_configAttribToCreateConfig.clear();
    for (auto& it : m_configAttribList) {

        if (it.value != VA_ATTRIB_NOT_SUPPORTED)
            m_configAttribToCreateConfig.push_back(it);
    }

    ASSERT_STATUS(vaCreateConfig(
        m_vaDisplay, profile, entrypoint, &m_configAttribToCreateConfig[0],
        m_configAttribToCreateConfig.size(), &m_configID));

    EXPECT_TRUE(m_configID > 0);

    doQueryConfigAttributes(profile, entrypoint);
}

void VAAPIFixture::doDestroyConfig()
{
    ASSERT_STATUS(vaDestroyConfig(m_vaDisplay, m_configID));
}

void VAAPIFixture::doQuerySurfacesWithConfigAttribs(VAProfile profile,
                                                    VAEntrypoint entrypoint)
{
    std::vector<VASurfaceAttrib> m_querySurfaceAttribList;
    uint32_t queryNumSurfaceAttribs;

    doCreateConfigWithAttrib(profile, entrypoint);

    ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
                                           NULL,
                                           &queryNumSurfaceAttribs));
    EXPECT_TRUE(queryNumSurfaceAttribs > 0);
    m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);

    ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
                                           &m_querySurfaceAttribList[0],
                                           &queryNumSurfaceAttribs));

    EXPECT_TRUE(queryNumSurfaceAttribs > 0);
    EXPECT_TRUE(queryNumSurfaceAttribs <= m_querySurfaceAttribList.size());
    m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);

    for (auto& it : m_querySurfaceAttribList) {

        unsigned int flags
            = 0 | VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;

        EXPECT_NE(it.flags & flags,
                  (unsigned int)VA_SURFACE_ATTRIB_NOT_SUPPORTED);
        EXPECT_TRUE((it.value.type >= VAGenericValueTypeInteger)
                    && it.value.type <= VAGenericValueTypeFunc);
    }
}

inline bool isSurfaceAttribInList(VASurfaceAttrib surfaceAttrib,
                                  VASurfaceAttribType surfaceAttribType)
{
    return surfaceAttrib.type == surfaceAttribType;
}

void VAAPIFixture::doGetMaxSurfaceResolution(
    VAProfile profile, VAEntrypoint entrypoint,
    std::pair<uint32_t, uint32_t>& maxResolution)
{
    std::vector<VASurfaceAttrib>::iterator it;
    doQuerySurfacesNoConfigAttribs(profile, entrypoint);
    it = std::find_if(m_querySurfaceAttribList.begin(),
                      m_querySurfaceAttribList.end(),
                      std::bind(isSurfaceAttribInList, std::placeholders::_1,
                                VASurfaceAttribMaxWidth));

    EXPECT_TRUE(it != m_querySurfaceAttribList.end());

    EXPECT_EQ(it->value.type, VAGenericValueTypeInteger);

    maxResolution.first = it->value.value.i;

    it = std::find_if(m_querySurfaceAttribList.begin(),
                      m_querySurfaceAttribList.end(),
                      std::bind(isSurfaceAttribInList, std::placeholders::_1,
                                VASurfaceAttribMaxHeight));

    EXPECT_TRUE(it != m_querySurfaceAttribList.end());

    EXPECT_EQ(it->value.type, VAGenericValueTypeInteger);

    maxResolution.second = it->value.value.i;
}

void VAAPIFixture::doCreateConfigNoAttrib(VAProfile profile,
                                          VAEntrypoint entrypoint)
{

    ASSERT_STATUS(
        vaCreateConfig(m_vaDisplay, profile, entrypoint, NULL, 0, &m_configID));

    EXPECT_TRUE(m_configID > 0);

    doQueryConfigAttributes(profile, entrypoint);
}

void VAAPIFixture::doQueryConfigAttributes(VAProfile profile,
                                           VAEntrypoint entrypoint,
                                           VAStatus expectation)
{
    VAProfile queryProfile;
    VAEntrypoint queryEntrypoint;
    int queryNumConfigAttribs;

    m_queryConfigAttribList.resize(m_maxConfigAttributes); // va-api requirement

    ASSERT_EQ(vaQueryConfigAttributes(
                  m_vaDisplay, m_configID, &queryProfile, &queryEntrypoint,
                  &m_queryConfigAttribList[0], &queryNumConfigAttribs),
              expectation);

    if (expectation == VA_STATUS_SUCCESS) {
        m_queryConfigAttribList.resize(queryNumConfigAttribs);
        EXPECT_EQ(queryProfile, profile);
        EXPECT_EQ(queryEntrypoint, entrypoint);
        EXPECT_TRUE(queryNumConfigAttribs > 0);

        m_queryConfigAttribList.resize(queryNumConfigAttribs);

        // reported Config Attributes should be supported
        for (auto& it : m_queryConfigAttribList) {
            EXPECT_NE(it.value, VA_ATTRIB_NOT_SUPPORTED);
        }
    }
}

void VAAPIFixture::doQuerySurfacesNoConfigAttribs(VAProfile profile,
                                                  VAEntrypoint entrypoint)
{
    uint32_t queryNumSurfaceAttribs;

    doCreateConfigNoAttrib(profile, entrypoint);

    ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
                                           NULL,
                                           &queryNumSurfaceAttribs));
    EXPECT_TRUE(queryNumSurfaceAttribs > 0);
    m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);

    ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
                                           &m_querySurfaceAttribList[0],
                                           &queryNumSurfaceAttribs));

    EXPECT_TRUE(queryNumSurfaceAttribs > 0);
    EXPECT_TRUE(queryNumSurfaceAttribs <= m_querySurfaceAttribList.size());
    m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);

    for (auto& it : m_querySurfaceAttribList) {

        unsigned int flags
            = 0 | VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;

        EXPECT_NE(it.flags & flags,
                  (unsigned int)VA_SURFACE_ATTRIB_NOT_SUPPORTED);
        EXPECT_TRUE((it.value.type >= VAGenericValueTypeInteger)
                    && it.value.type <= VAGenericValueTypeFunc);
    }
}

inline bool isConfigAttribInList(VAConfigAttrib configAttrib,
                                 VAConfigAttribType type)
{
    return configAttrib.type == type;
}

void VAAPIFixture::doCreateSurfaces(VAProfile profile, VAEntrypoint entrypoint,
                                    std::pair<uint32_t, uint32_t> resolution)
{
    VASurfaceAttrib* attribList = NULL;
    uint32_t numAttribs = 0;
    // when ConfigAttribs were not queried just do YUV420 as it is considered
    // the universal supported format by the driver.  RT formats depend on
    // profile and entrypoint.
    unsigned int formats = VA_RT_FORMAT_YUV420;

    m_surfaceID.resize(10);

    if (!m_querySurfaceAttribList.empty()) {
        numAttribs = m_querySurfaceAttribList.size();
        attribList = &m_querySurfaceAttribList[0];
    }

    if (!m_queryConfigAttribList.empty()) {
        std::vector<VAConfigAttrib>::iterator it = std::find_if(
            m_queryConfigAttribList.begin(), m_queryConfigAttribList.end(),
            std::bind(isConfigAttribInList, std::placeholders::_1,
                      VAConfigAttribRTFormat));
        formats = it->value;
    }

    for (auto& itFormat : m_vaRTFormats) {
        unsigned int currentFormat = formats & itFormat;

        if (currentFormat) {

            ASSERT_STATUS(vaCreateSurfaces(
                m_vaDisplay, currentFormat, resolution.first, resolution.second,
                &m_surfaceID[0], 10, attribList, numAttribs));
            formats &= ~itFormat;
        }
    }
}

void VAAPIFixture::doCreateContext(std::pair<uint32_t, uint32_t> resolution,
                                   VAStatus expectation)
{
    m_contextID = 0;
    ASSERT_EQ(vaCreateContext(m_vaDisplay, m_configID, resolution.first,
                              resolution.second, VA_PROGRESSIVE,
                              &m_surfaceID[0], m_surfaceID.size(),
                              &m_contextID),
              expectation);
}

void VAAPIFixture::doDestroyContext(VAStatus expectation)
{
    ASSERT_EQ(vaDestroyContext(m_vaDisplay, m_contextID), expectation);
}

void VAAPIFixture::doCreateBuffer(VABufferType bufferType)
{
    ASSERT_STATUS(vaCreateBuffer(m_vaDisplay, m_contextID, bufferType,
                                 sizeof(bufferType), 1, NULL, &m_bufferID));
}

void VAAPIFixture::doDestroyBuffer()
{
    ASSERT_STATUS(vaDestroyBuffer(m_vaDisplay, m_bufferID));
}

void VAAPIFixture::doCreateConfig(VAProfile profile, VAEntrypoint entrypoint)
{
    m_configID = 0;
    ASSERT_STATUS(
        vaCreateConfig(m_vaDisplay, profile, entrypoint, NULL, 0, &m_configID));
    EXPECT_NE(m_configID, 0u);
}

void VAAPIFixture::doCreateConfigToFail(VAProfile profile,
                                        VAEntrypoint entrypoint, int error)
{
    VAStatus vaStatus = VA_STATUS_SUCCESS;

    m_configID = 0;

    vaStatus = vaCreateConfig(m_vaDisplay, profile, entrypoint, NULL, 0,
                              &m_configID);
    ASSERT_EQ(vaStatus, error);

    EXPECT_EQ(m_configID, 0u);

    m_queryConfigAttribList.resize(m_maxConfigAttributes); // va-api requirement

    doQueryConfigAttributes(profile, entrypoint,
                            VA_STATUS_ERROR_INVALID_CONFIG);

    ASSERT_EQ(vaDestroyConfig(m_vaDisplay, m_configID),
              VA_STATUS_ERROR_INVALID_CONFIG);
}

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

TEST_F(VAAPIFixture, getDisplay)
{
    VADisplay vaDisplay;

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

void VAAPIFixture::doLogSkipTest(VAProfile profile, VAEntrypoint entrypoint)
{
    RecordProperty("skipped", true);
    std::cout << "[ SKIPPED ]"
	      << " " << profile << " / " << entrypoint
	      << " not supported on this hardware" << std::endl;
}
} // namespace VAAPI
