#pragma once

#include "../frames/InputFrameMailbox.h"
#include "GLExtensions.h"

#include <cstdint>

class InputFrameTexture
{
public:
	InputFrameTexture() = default;
	InputFrameTexture(const InputFrameTexture&) = delete;
	InputFrameTexture& operator=(const InputFrameTexture&) = delete;
	~InputFrameTexture();

	GLuint PollAndUpload(InputFrameMailbox* mailbox);
	GLuint Texture() const { return mTexture; }
	uint64_t UploadedFrames() const { return mUploadedFrames; }
	uint64_t UploadMisses() const { return mUploadMisses; }
	double LastUploadMilliseconds() const { return mLastUploadMilliseconds; }
	bool LastFrameFormatSupported() const { return mLastFrameFormatSupported; }
	void ShutdownGl();

private:
	bool EnsureTexture(const InputFrame& frame);
	bool EnsureRawUyvyTexture(const InputFrame& frame);
	bool EnsureDecodeProgram();
	void UploadBgra8FrameFlippedVertically(const InputFrame& frame);
	void UploadUyvy8Frame(const InputFrame& frame);
	void DecodeUyvy8Frame(const InputFrame& frame);
	void DestroyDecodeResources();
	static bool CompileShader(GLenum shaderType, const char* source, GLuint& shader);
	static bool LinkProgram(GLuint vertexShader, GLuint fragmentShader, GLuint& program);

	GLuint mTexture = 0;
	GLuint mRawTexture = 0;
	GLuint mDecodeFramebuffer = 0;
	GLuint mDecodeVertexArray = 0;
	GLuint mDecodeProgram = 0;
	GLuint mDecodeVertexShader = 0;
	GLuint mDecodeFragmentShader = 0;
	unsigned mWidth = 0;
	unsigned mHeight = 0;
	unsigned mRawWidth = 0;
	unsigned mRawHeight = 0;
	uint64_t mUploadedFrames = 0;
	uint64_t mUploadMisses = 0;
	double mLastUploadMilliseconds = 0.0;
	bool mLastFrameFormatSupported = true;
};
