#pragma once
#include "c-ops.hh"
#include "ui-shaders.hh"
#include "ui-texture.hh"


namespace ops {

struct T_OpContext
{
	T_OpProgram& program;		// The program

	uint32_t instrPtr;		// Instruction pointer
	bool aborted{ false };		// Did the program fail?

	T_Array< T_OpValue > values;	// VM data
	T_Array< T_OpValue > stack;	// Main VM stack
	T_Array< float > initialInputs;	// Initial input values

	T_OpValue wreg;			// Work register
	double x87stack[ 8 ];		// x87 FPU emulation stack
	uint32_t x87sp;			// x87 FPU emulation stack pointer

	P_SyncOverrideSection installOverrides;	// Install UI overrides

	// Allocated resources
	T_Array< T_OwnPtr< T_Rendertarget > > framebuffers;
	T_Array< T_OwnPtr< T_ShaderProgram > > programs;
	T_Array< T_OwnPtr< T_ShaderPipeline > > pipelines;
	T_Array< T_OwnPtr< T_TextureSampler > > samplers;
	T_Array< T_OwnPtr< T_Texture > > textures;

	T_Array< T_String > profiling;	// Profiling sections that have been started
	int32_t curFb{ -1 };		// Index of current framebuffer

	enum E_RunTarget {
		R_INIT ,
		R_RENDER
	};

	explicit T_OpContext( T_OpProgram& program ) noexcept;
	void run( E_RunTarget target ,
			float time ,
			float width ,
			float height );

    private:
	void ensureStack( T_Op const& op ,
			uint32_t min );
	void ensureFpuStack( T_Op const& op ,
			uint32_t minStacked ,
			uint32_t minFree );
	void checkAddress( T_Op const& op ,
			uint32_t address );
};

class X_OpFailure : public std::exception
{
    public:
	X_OpFailure( ) = delete;
	DEF_COPY( X_OpFailure );
	DEF_MOVE( X_OpFailure );

	X_OpFailure(
		T_Op const& op ,
		T_String error ) noexcept;

	T_Op const& op( ) const noexcept
		{ return *op_; }
	T_String const& error( ) const noexcept
		{ return error_; }

	char const* what( ) const noexcept override;

    private:
	T_Op const* op_;
	T_String error_;
	T_String fullMessage_;
};

} // namespace ops