/* Copyright (c) 2015-2021 The Khronos Group Inc.
 * Copyright (c) 2015-2021 Valve Corporation
 * Copyright (c) 2015-2021 LunarG, Inc.
 * Copyright (C) 2015-2021 Google Inc.
 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 *
 * 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: Courtney Goeltzenleuchter <courtneygo@google.com>
 * Author: Tobin Ehlis <tobine@google.com>
 * Author: Chris Forbes <chrisf@ijw.co.nz>
 * Author: Mark Lobodzinski <mark@lunarg.com>
 * Author: Dave Houlton <daveh@lunarg.com>
 * Author: John Zulauf <jzulauf@lunarg.com>
 * Author: Tobias Hector <tobias.hector@amd.com>
 * Author: Jeremy Gebben <jeremyg@lunarg.com>
 */
#pragma once

#include "vulkan/vulkan.h"
#include "vk_object_types.h"
#include "vk_layer_data.h"
#include "vk_layer_logging.h"

#include <atomic>

// Intentionally ignore VulkanTypedHandle::node, it is optional
inline bool operator==(const VulkanTypedHandle &a, const VulkanTypedHandle &b) NOEXCEPT {
    return a.handle == b.handle && a.type == b.type;
}
namespace std {
template <>
struct hash<VulkanTypedHandle> {
    size_t operator()(VulkanTypedHandle obj) const NOEXCEPT { return hash<uint64_t>()(obj.handle) ^ hash<uint32_t>()(obj.type); }
};
}  // namespace std

class BASE_NODE {
  public:
    using NodeSet = layer_data::unordered_set<BASE_NODE *>;
    using NodeList = small_vector<BASE_NODE *, 4>;

    template <typename Handle>
    BASE_NODE(Handle h, VulkanObjectType t) : handle_(h, t), destroyed_(false) {}

    virtual ~BASE_NODE() { Destroy(); }

    virtual void Destroy() {
        Invalidate();
        destroyed_ = true;
    }

    bool Destroyed() const { return destroyed_; }

    const VulkanTypedHandle &Handle() const { return handle_; }
    VulkanObjectType Type() const { return handle_.type; }

    virtual bool InUse() const {
        bool result = false;
        for (auto& node: parent_nodes_) {
            result |= node->InUse();
            if (result) {
                break;
            }
        }
        return result;
    }

    virtual bool AddParent(BASE_NODE *parent_node) {
        auto result = parent_nodes_.emplace(parent_node);
        return result.second;
    }

    virtual void RemoveParent(BASE_NODE *parent_node) {
        parent_nodes_.erase(parent_node);
    }

    void Invalidate(bool unlink = true) {
        NodeList invalid_nodes;
        invalid_nodes.emplace_back(this);
        for (auto& node: parent_nodes_) {
            node->NotifyInvalidate(invalid_nodes, unlink);
        }
        if (unlink) {
            parent_nodes_.clear();
        }
    }
  protected:
    // NOTE: the entries in invalid_nodes will likely be destroyed & deleted
    // after the NotifyInvalidate() calls finish.
    virtual void NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) {
        if (parent_nodes_.size() == 0) {
            return;
        }
        NodeList up_nodes = invalid_nodes;
        up_nodes.emplace_back(this);
        for (auto& node: parent_nodes_) {
            node->NotifyInvalidate(up_nodes, unlink);
        }
        if (unlink) {
            parent_nodes_.clear();
        }
    }

    VulkanTypedHandle handle_;

    // Set to true when the API-level object is destroyed, but this object may
    // hang around until its shared_ptr refcount goes to zero.
    bool destroyed_;

    // Set of immediate parent nodes for this object. For an in-use object, the
    // parent nodes should form a tree with the root being a command buffer.
    NodeSet parent_nodes_;
};

class REFCOUNTED_NODE : public BASE_NODE {
private:
    // Track if command buffer is in-flight
    std::atomic_int in_use_;

public:
    template <typename Handle>
    REFCOUNTED_NODE(Handle h, VulkanObjectType t) : BASE_NODE(h, t), in_use_(0) { }

    void BeginUse() { in_use_.fetch_add(1); }

    void EndUse() { in_use_.fetch_sub(1); }

    void ResetUse() { in_use_.store(0); }

    bool InUse() const override { return (in_use_.load() > 0) || BASE_NODE::InUse(); }
};
