/* Copyright (c) 2021 The Khronos Group Inc.
 * Copyright (c) 2021 Valve Corporation
 * Copyright (c) 2021 LunarG, Inc.
 * Copyright (C) 2021 Google Inc.
 *
 * 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.
 *
 * Author: Jeremy Gebben <jeremyg@lunarg.com>
 */
#pragma once

#include <cstdint>
#include <string>
#include <sstream>
#include <limits>

#include "vk_layer_data.h"
namespace core_error {
// structure to track where a validation error occurs, and capture enough information
// to generate the start of a log message and find the correct VUID for many commonvalidity errors.
//
// usage example:
// Location outer(Func::vkCmdPipelineBarrier, Struct::VkImageMemoryBarrier);
//     auto struct_level = outer.dot(Field::pImageMemoryBarriers, i);
//        auto field_level = struct_level.dot(Field::srcAccessMask);
//        std::cout << field_level.Message() << std::endl;
// will print:
//        vkCmdPipelineBarrier(): pImageMemoryBarriers[42].srcAccessMask
// VUIDs can be found for an error in generic code using a combination of the
// function, structure, and fieldmembers.

/// TODO: these enums can eventually be autogenerated from vk.xml
enum class Func {
    Empty = 0,
    vkQueueSubmit,
    vkQueueSubmit2KHR,
    vkCmdSetEvent,
    vkCmdSetEvent2KHR,
    vkCmdResetEvent,
    vkCmdResetEvent2KHR,
    vkCmdPipelineBarrier,
    vkCmdPipelineBarrier2KHR,
    vkCmdWaitEvents,
    vkCmdWaitEvents2KHR,
    vkCmdWriteTimestamp,
    vkCmdWriteTimestamp2KHR,
    vkCreateRenderPass,
    vkCreateRenderPass2,
    vkQueueBindSparse,
    vkSignalSemaphore,
};

const std::string& String(Func func);

enum class Struct {
    Empty = 0,
    VkMemoryBarrier,
    VkMemoryBarrier2KHR,
    VkBufferMemoryBarrier,
    VkImageMemoryBarrier,
    VkBufferMemoryBarrier2KHR,
    VkImageMemoryBarrier2KHR,
    VkSubmitInfo,
    VkSubmitInfo2KHR,
    VkCommandBufferSubmitInfoKHR,
    VkSubpassDependency,
    VkSubpassDependency2,
    VkBindSparseInfo,
    VkSemaphoreSignalInfo,
    VkSemaphoreSubmitInfoKHR,
    VkProtectedSubmitInfo,
};

const std::string& String(Struct s);

enum class Field {
    Empty = 0,
    oldLayout,
    newLayout,
    image,
    buffer,
    pMemoryBarriers,
    pBufferMemoryBarriers,
    pImageMemoryBarriers,
    offset,
    size,
    subresourceRange,
    srcAccessMask,
    dstAccessMask,
    srcStageMask,
    dstStageMask,
    pNext,
    pWaitDstStageMask,
    pWaitSemaphores,
    pSignalSemaphores,
    pWaitSemaphoreInfos,
    pWaitSemaphoreValues,
    pSignalSemaphoreInfos,
    pSignalSemaphoreValues,
    stage,
    stageMask,
    value,
    pCommandBuffers,
    pSubmits,
    pCommandBufferInfos,
    semaphore,
    commandBuffer,
    dependencyFlags,
    pDependencyInfo,
    pDependencyInfos,
    srcQueueFamilyIndex,
    dstQueueFamilyIndex,
    queryPool,
    pDependencies,
    pipelineStage,
};

const std::string& String(Field field);

struct Location {
    static const uint32_t kNoIndex = std::numeric_limits<uint32_t>::max();

    // name of the vulkan function we're checking
    Func function;

    Struct structure;
    Field field;
    // optional index if checking an array.
    uint32_t index;
    const Location* prev;

    Location(Func func, Struct s, Field f = Field::Empty, uint32_t i = kNoIndex)
        : function(func), structure(s), field(f), index(i), prev(nullptr) {}
    Location(Func func, Field f = Field::Empty, uint32_t i = kNoIndex)
        : function(func), structure(Struct::Empty), field(f), index(i), prev(nullptr) {}
    Location(const Location& prev_loc, Struct s, Field f, uint32_t i)
        : function(prev_loc.function), structure(s), field(f), index(i), prev(&prev_loc) {}

    void AppendFields(std::ostream &out) const;
    std::string Message() const {
        std::stringstream out;
        out << StringFunc() << "(): ";
        AppendFields(out);
        return out.str();
    }

    // the dot() method is for walking down into a structure that is being validated
    // eg:  loc.dot(Field::pMemoryBarriers, 5).dot(Field::srcStagemask)
    Location dot(Struct s, Field sub_field, uint32_t sub_index = kNoIndex) const {
        Location result(*this, s, sub_field, sub_index);
        return result;
    }
    Location dot(Field sub_field, uint32_t sub_index = kNoIndex) const {
        Location result(*this, this->structure, sub_field, sub_index);
        return result;
    }

    const std::string& StringFunc() const { return String(function); }
    const std::string& StringStruct() const { return String(structure); }
    const std::string& StringField() const { return String(field); }
};

template <typename VuidFunctor>
struct LocationVuidAdapter {
    const Location loc;
    VuidFunctor vuid_functor;
    const char* FuncName() const {
        // the returned reference from loc must be valid for lifespan of loc, at least.
        const std::string& function = loc.StringFunc();
        return function.c_str();
    }
    const char* Vuid() const {
        // the returned reference from functor must be valid for lifespan of vuid_functor, at least.
        const std::string& vuid = vuid_functor(loc);
        return vuid.c_str();
    }
    template <typename... Args>
    LocationVuidAdapter(const Location& loc_, const Args&... args) : loc(loc_), vuid_functor(args...) {}
};

struct LocationCapture {
    LocationCapture(const Location& loc);
    const Location& Get() const { return capture.back(); }

  protected:
    // TODO: Optimize this for "new" minimization
    using CaptureStore = small_vector<Location, 2>;
    const Location* Capture(const Location& loc, CaptureStore::size_type depth);
    CaptureStore capture;
};

// Key for use in tables of VUIDs.
//
// Fuzzy match rules:
//  key.function OR key.structure may be Empty
//  loc.structure may be Empty
//  key.field may be Empty
//  if key.recurse_field is true, key.field can match loc.field or any fields in loc.prev
//
struct Key {
    Func function;
    Struct structure;
    Field field;
    bool recurse_field;
    Key(Struct r, Field f = Field::Empty, bool recurse = false)
        : function(Func::Empty), structure(r), field(f), recurse_field(recurse) {}
    Key(Func fn, Field f = Field::Empty, bool recurse = false)
        : function(fn), structure(Struct::Empty), field(f), recurse_field(recurse) {}
};

bool operator==(const Key& key, const Location& loc);

// Entry in a VUID lookup table
struct Entry {
    Key k;
    std::string v;
};

// look for a matching VUID in a vector or array-ish table
template <typename Table>
static const std::string& FindVUID(const Location& loc, const Table& table) {
    static const std::string empty;
    auto predicate = [&loc](const Entry& entry) { return entry.k == loc; };

    // consistency check: there should never be more than 1 match in a table
    assert(std::count_if(table.begin(), table.end(), predicate) <= 1);

    const auto pos = std::find_if(table.begin(), table.end(), predicate);
    return (pos != table.end()) ? pos->v : empty;
}

// 2-level look up where the outer container is a map where we need to find
// different VUIDs for different values of an enum or bitfield
template <typename OuterKey, typename Table>
static const std::string& FindVUID(OuterKey key, const Location& loc, const Table& table) {
    static const std::string empty;
    const auto entry = table.find(key);
    if (entry != table.end()) {
        return FindVUID(loc, entry->second);
    }
    return empty;
}

}  // namespace core_error
