// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MSD_INTEL_CONTEXT_H
#define MSD_INTEL_CONTEXT_H

#include "command_buffer.h"
#include "magma_util/semaphore_port.h"
#include "magma_util/status.h"
#include "msd.h"
#include "msd_intel_buffer.h"
#include "ppgtt.h"
#include "ringbuffer.h"
#include "types.h"
#include <map>
#include <memory>
#include <queue>
#include <thread>

class MsdIntelConnection;

// Abstract base context.
class MsdIntelContext {
public:
    MsdIntelContext(std::shared_ptr<AddressSpace> address_space) : address_space_(address_space)
    {
        DASSERT(address_space_);
    }

    virtual ~MsdIntelContext() {}

    void SetEngineState(EngineCommandStreamerId id, std::unique_ptr<MsdIntelBuffer> context_buffer,
                        std::unique_ptr<Ringbuffer> ringbuffer);

    virtual bool Map(std::shared_ptr<AddressSpace> address_space, EngineCommandStreamerId id);
    virtual bool Unmap(EngineCommandStreamerId id);

    virtual std::weak_ptr<MsdIntelConnection> connection()
    {
        return std::weak_ptr<MsdIntelConnection>();
    }

    virtual bool killed() { return false; }

    virtual void Kill() { magma::log(magma::LOG_WARNING, "Attemping to kill the global context"); }

    // Gets the gpu address of the context buffer if mapped.
    bool GetGpuAddress(EngineCommandStreamerId id, gpu_addr_t* addr_out);
    bool GetRingbufferGpuAddress(EngineCommandStreamerId id, gpu_addr_t* addr_out);

    MsdIntelBuffer* get_context_buffer(EngineCommandStreamerId id)
    {
        auto iter = state_map_.find(id);
        return iter == state_map_.end() ? nullptr : iter->second.context_buffer.get();
    }

    void* GetCachedContextBufferCpuAddr(EngineCommandStreamerId id)
    {
        auto iter = state_map_.find(id);
        if (iter == state_map_.end())
            return nullptr;
        if (!iter->second.context_buffer_cpu_addr) {
            MsdIntelBuffer* context_buffer = iter->second.context_buffer.get();
            if (!context_buffer)
                return nullptr;
            if (!context_buffer->platform_buffer()->MapCpu(&iter->second.context_buffer_cpu_addr))
                return DRETP(nullptr, "Failed to map context buffer");
        }
        return iter->second.context_buffer_cpu_addr;
    }

    Ringbuffer* get_ringbuffer(EngineCommandStreamerId id)
    {
        auto iter = state_map_.find(id);
        return iter == state_map_.end() ? nullptr : iter->second.ringbuffer.get();
    }

    bool IsInitializedForEngine(EngineCommandStreamerId id)
    {
        return state_map_.find(id) != state_map_.end();
    }

    std::queue<std::unique_ptr<MappedBatch>>& pending_batch_queue() { return pending_batch_queue_; }

    std::shared_ptr<AddressSpace> exec_address_space() { return address_space_; }

private:
    struct PerEngineState {
        std::shared_ptr<MsdIntelBuffer> context_buffer;
        std::unique_ptr<GpuMapping> context_mapping;
        std::unique_ptr<Ringbuffer> ringbuffer;
        void* context_buffer_cpu_addr = nullptr;
    };

    std::map<EngineCommandStreamerId, PerEngineState> state_map_;
    std::queue<std::unique_ptr<MappedBatch>> pending_batch_queue_;
    std::shared_ptr<AddressSpace> address_space_;

    friend class TestContext;
};

class ClientContext : public MsdIntelContext {
public:
    ClientContext(std::weak_ptr<MsdIntelConnection> connection,
                  std::shared_ptr<AddressSpace> address_space)
        : MsdIntelContext(std::move(address_space)), connection_(connection)
    {
    }

    ~ClientContext();

    magma::Status SubmitCommandBuffer(std::unique_ptr<CommandBuffer> cmd_buf);
    void Shutdown();

    std::weak_ptr<MsdIntelConnection> connection() override { return connection_; }

    bool killed() override { return killed_; }

    void Kill() override;

private:
    magma::Status SubmitPendingCommandBuffer(bool have_lock);

    std::weak_ptr<MsdIntelConnection> connection_;
    std::unique_ptr<magma::SemaphorePort> semaphore_port_;
    std::thread wait_thread_;
    std::mutex pending_command_buffer_mutex_;
    std::queue<std::unique_ptr<CommandBuffer>> pending_command_buffer_queue_;
    bool killed_ = false;
};

class MsdIntelAbiContext : public msd_context_t {
public:
    MsdIntelAbiContext(std::shared_ptr<ClientContext> ptr) : ptr_(std::move(ptr))
    {
        magic_ = kMagic;
    }

    static MsdIntelAbiContext* cast(msd_context_t* context)
    {
        DASSERT(context);
        DASSERT(context->magic_ == kMagic);
        return static_cast<MsdIntelAbiContext*>(context);
    }
    std::shared_ptr<ClientContext> ptr() { return ptr_; }

private:
    std::shared_ptr<ClientContext> ptr_;
    static const uint32_t kMagic = 0x63747874; // "ctxt"
};

#endif // MSD_INTEL_CONTEXT_H
