// Copyright 2019 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_IMG_CONNECTION_H
#define MSD_IMG_CONNECTION_H

#include <memory>
#include <vector>

#include "include/fuchsia_communication.h"
#include "magma_util/macros.h"
#include "msd.h"

typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
typedef struct _CONNECTION_DATA_ CONNECTION_DATA;
typedef struct PVRSRV_BRIDGE_PACKAGE_TAG PVRSRV_BRIDGE_PACKAGE;

class MsdImgBuffer;
class MsdImgSemaphore;

class MsdImgConnection : public msd_connection_t
{
public:
	class Owner
	{
	public:
		virtual PVRSRV_DEVICE_NODE* device_node() = 0;
	};

	// If the current thread is currently servicing a bridge request or other
	// operation on a connection, this will return a pointer to that connection.
	static MsdImgConnection* GetCurrentConnection();

	virtual ~MsdImgConnection();

	MsdImgConnection(Owner* owner, msd_client_id_t client_id);

	void AssertValid()
	{
		// Use volatile to ensure the compiler won't optimize the check out if
		// it realizes magic_ always == kMagic outside the constructor and
		// destructor.
		DASSERT(*const_cast<volatile int32_t*>(&magic_) == kMagic);
	}

	bool Init();
	magma_status_t ExecuteCommandBuffer(magma_system_command_buffer* command_buffer,
					    magma_system_exec_resource* exec_resources,
					    msd_buffer_t** buffers,
					    msd_semaphore_t** signal_semaphores);
	bool CopyFromUser(void* dest, const void* src, uint32_t size);
	bool CopyToUser(void* dest, const void* src, uint32_t size);


	static MsdImgConnection* Cast(msd_connection_t* msd_connection)
	{
		DASSERT(msd_connection);
		DASSERT(msd_connection->magic_ == kMagic);
		return static_cast<MsdImgConnection*>(msd_connection);
	}

	static MsdImgConnection* Cast(void* void_connection)
	{
		DASSERT(void_connection);
		auto msd_connection = static_cast<MsdImgConnection*>(void_connection);
		msd_connection->AssertValid();
		return msd_connection;
	}

	Owner* owner() const { return owner_; }
	msd_client_id_t client_id() const { return client_id_; }
	// This is unchecked and comes from the client, so it should only be used
	// for debug logging.
	uint64_t current_client_thread_id() const { return current_client_thread_id_; }

	char* client_name() { return client_name_; }

	// Takes ownership of an additional buffer that was sent along with a
	// command buffer. Once the buffer is taken, subsequent calls within the
	// same execution of a bridge command will return null.
	std::shared_ptr<MsdImgBuffer> TakeAdditionalBuffer();

	// Takes ownership of an additional semaphore that was sent along with a
	// command buffer. Once the semaphore is taken, subsequent calls within the
	// same execution of a bridge command will return null.
	std::shared_ptr<MsdImgSemaphore> TakeAdditionalSemaphore();

private:
	friend class TestMsdImgConnection;
	friend class TestOsFunc;

	magma_status_t ProcessCommandBuffer(magma_system_command_buffer* command_buffer,
					    magma_system_exec_resource* exec_resources,
					    msd_buffer_t** buffers,
					    msd_semaphore_t** signal_semaphores,
					    PVRSRV_BRIDGE_PACKAGE* package_out,
					    volatile FuchsiaImgCommandPayload** payload_out,
					    std::vector<std::shared_ptr<MsdImgSemaphore>>* semaphores_out);
	void CleanupAfterCommand(volatile FuchsiaImgCommandPayload* payload,
				 const std::vector<std::shared_ptr<MsdImgSemaphore>>& semaphores,
				 bool success);

	static const uint32_t kMagic = 'icon';
	Owner* owner_;
	msd_client_id_t client_id_;
	CONNECTION_DATA* connection_data_ = nullptr;
	char client_name_[32];
	uint64_t current_client_thread_id_;

	// This member is only valid when ExecuteCommandBuffer is executing.
	std::shared_ptr<MsdImgBuffer> payload_buffer_;

	std::shared_ptr<MsdImgBuffer> additional_buffer_;
	std::shared_ptr<MsdImgSemaphore> additional_semaphore_;
};

#endif // MSD_IMG_CONNECTION_H
