namespace PhpefRuntimeEmbed {
    private static bool initialized = false;

    [CCode (cname = "phpef_runtime_embed_register_resource_stream_wrapper")]
    private extern void register_resource_stream_wrapper();

    [CCode (cname = "phpef_runtime_embed_unregister_resource_stream_wrapper")]
    private extern void unregister_resource_stream_wrapper();

    public void engine_start(string[] args) {
        PwPhpBytecode.engine_start(args.length, args);
        register_resource_stream_wrapper();
        initialized = true;
    }

    public void engine_stop() {
        if (initialized) {
            unregister_resource_stream_wrapper();
            PwPhpBytecode.engine_stop();
            initialized = false;
        }
    }

    public void ensure_initialized() {
        if (!initialized) {
            string[] argv = { "phpef-runtime-embed" };
            engine_start(argv);
        }
    }

    public void print_zend_identity() {
        ensure_initialized();
        PwPhpBytecode.print_zendid();
    }

    public void eval_code(string debugname, string code) {
        ensure_initialized();
        PwPhpBytecode.exec(debugname, code);
    }

    [CCode (cname = "phpef_runtime_embed_lookup_constant")]
    private extern PhpefRuntimeCore.Zval? lookup_constant(string name);

    public PhpefRuntimeCore.Zval get_constant(string name) throws Error {
        ensure_initialized();
        var result = lookup_constant(name);
        if (result == null) {
            PhpefRuntimeCore.throw_exception("Error", PhpefRuntimeCore.Zval.from_string("Undefined constant \"" + name + "\""));
            return PhpefRuntimeCore.Zval.from_null();
        }
        return result;
    }
}
