#pragma once

#include "constants.hpp"
#include "godot_cpp/classes/ref_counted.hpp"

namespace CoborVM
{
	class CoborVirtualMachine : public godot::RefCounted
	{
		GDCLASS(CoborVirtualMachine, godot::RefCounted)

	protected:
		static void _bind_methods();

	private:
		std::vector<ExecutableStep> program;
		std::vector<int32_t> register_memory;

	public:
		CoborVirtualMachine() = default;
		~CoborVirtualMachine() override = default;

		godot::PackedStringArray parse_source_code(godot::String source_code);
		godot::String set_registers(int size, godot::PackedInt32Array preloaded_values);
		godot::PackedInt32Array get_registers();
		int get_program_counter();
		int get_program_size();
		godot::String run_step();
		godot::String run_all();

	private:
		// Execution
		godot::String run_executable_step(ExecutableStep step);
		// Parsing
		bool string_to_instruction(godot::String command_string, Instruction &outInstruction);
		bool instruction_to_executable_step(Instruction instruction, godot::PackedStringArray line, ExecutableStep &outExecutableStep);
		bool validate_and_parse_pointer(const godot::String &arg, int &outValue);
		bool validate_and_parse_literal(const godot::String &arg, int &outValue);
	};
}