/******************************************************************************
*	File		-	wren_state.h
*	Author		-	Joey Pollack
*	Date		-	2022/10/25 (y/m/d)
*	Mod Date	-	2022/10/25 (y/m/d)
*	Description	-	Manages the wren vm, runs scripts. This is the main
*                   interface for wren.
******************************************************************************/

#ifndef LUNARIUM_WREN_STATE_H_
#define LUNARIUM_WREN_STATE_H_

#include <core/common_defs.h>
#include <utils/op_res.h>

#include <wren.hpp>
#include <string>
#include <vector>

namespace lunarium
{
    enum class WrenParamType
    {
        WPT_DOUBLE,
        WPT_BOOL,
        WPT_STR,
    };

    struct WrenParameter
    {
        WrenParamType Type;
        union
        {
            double Double;
            float Float;
            int Int;
            char Char;
            bool Bool;
            char* String;
        } As;
    };

    class WrenScript;

    typedef WrenForeignMethodFn ForeignMethod;
    typedef WrenFinalizerFn Finalizer; 

    class WrenState
    {
    public: 
        struct ForeignMethodDesc
        {
            std::string Module;
            std::string Class;
            bool IsStatic;
            std::string Signature;
            ForeignMethod FM;

            bool operator==(const ForeignMethodDesc& rhs)
            {
                return (Module == rhs.Module && Class == rhs.Class && IsStatic == rhs.IsStatic && Signature == rhs.Signature);
            }
        };

        struct ForeignClassDesc
        {
            std::string Module;
            std::string Class;
            u32 ForeignDataSize;

            WrenForeignClassMethods FCM;

            bool operator==(const ForeignClassDesc& rhs)
            {
                return (Module == rhs.Module && Class == rhs.Class);
            }
        };


    public:
        ~WrenState();
        OpRes Initialize();
        void Shutdown();
        u32 GetLogCat() const;

        void RegisterForeignMethod(ForeignMethodDesc method_desc);
        void RegisterForeignClass(ForeignClassDesc class_desc);

        void RunScript(WrenScript* script);
        void RunSnippet(std::string name, std::string code);

        WrenHandle* GetWrenClassHandle(std::string from_module, std::string class_name);
        WrenHandle* GetWrenMethodHandle(std::string method_signature);  // signature example (mehtod takes 2 parameters): method_name(_,_)
        void CallWrenMethod(WrenHandle* method, WrenHandle* receiver, std::vector<WrenParameter> params, std::string name_tag);
        void ReleaseWrenHandle(WrenHandle* handle);



public:
    // CALL BACKS
    static void WriteFN(WrenVM* vm, const char* text);
    static void ErrorFN(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message);
    static WrenForeignMethodFn BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature);
    static WrenForeignClassMethods BindForeignClassFN(WrenVM* vm, const char* module, const char* className);



    private:
        static u32 mLogCat;
        WrenVM* mpVM;
        static std::vector<ForeignMethodDesc> mForeignMethods;
        static std::vector<ForeignClassDesc> mForeignClasses;

    };
}

#endif	// LUNARIUM_WREN_STATE_H_