local m=require(script.Parent.Parent.TrueSignal)local q=require(script.Parent.prepArgs)local x={}x.__index=function(m,q)return rawget(x,q)or rawget(m,q)or m._internal[q]end x.__newindex=function(m,q,x)if q=="\079\110\067\108\105\101\110\116\073\110\118\111\107\101"then m._internal.OnClientInvoke=x for m,q in pairs(m._signals)do q:fire(x(table.unpack(q.args)))q:destroy()end table.clear(m._signals)end end function x._new(m,q,L)local E={}E.name=m E.destroyed=false E._server=q E._client=L E._internal={}E._signals={}E._client._remoteFunctions[m]=E return setmetatable(E,x)end function x._invokeClient(x,...)if x._internal.OnClientInvoke then return x._internal.OnClientInvoke(...)end local L=m.new()L.args=table.pack(q(...))table.insert(x._signals,L)return L:wait()end function x._destroy(m)m._client._remoteFunctions[m.name]=nil for m,q in pairs(m._signals)do q:destroy()end m.destroyed=true end function x.invokeServer(m,...)local x={q(...)}if m._server._remoteFunctions[m.name]then return(m._server:getRemoteFunction(m.name)):_invokeServer(m._client,table.unpack(x))end end x.InvokeServer=x.invokeServer return x
local TrueSignal = require(script.Parent.Parent.TrueSignal)

local prepArgs = require(script.Parent.prepArgs)

--[=[
    RemoteFunctionClient class

    @class RemoteFunctionClient
]=]
local RemoteFunctionClient = {}

RemoteFunctionClient.__index = function(self, key)
    return rawget(RemoteFunctionClient, key) or rawget(self, key) or self._internal[key]
end


RemoteFunctionClient.__newindex = function(self, key, fn)
    if key == "OnClientInvoke" then
        self._internal.OnClientInvoke = fn

        for _, signal in pairs(self._signals) do
            signal:fire(fn(table.unpack(signal.args)))
            signal:destroy()
        end
        
        table.clear(self._signals)
    end
end

--[=[
    Constructs a new RemoteFunctionClient object

    @param name string
    @param server Server
    @param client Client
    @return RemoteFunctionClient

    @private
]=]
function RemoteFunctionClient._new(name, server, client)
    local self = {}

    self.name = name
    self.destroyed = false
    
    self._server = server
    self._client = client
    
    self._internal = {}
    self._signals = {}

    self._client._remoteFunctions[name] = self

    return setmetatable(self, RemoteFunctionClient)
end

--[=[
    Called by RemoteFunctionServer to invoke the client

    @param ... any
    @return any
    
    @private
]=]
function RemoteFunctionClient:_invokeClient(...)
    if self._internal.OnClientInvoke then
        return self._internal.OnClientInvoke(...)
    end

    local signal = TrueSignal.new()
    signal.args = table.pack(prepArgs(...))

    table.insert(self._signals, signal)

    return signal:wait()
end

--[=[
    Called by RemoteFunctionServer to clean up

    @private
]=]
function RemoteFunctionClient:_destroy()
    self._client._remoteFunctions[self.name] = nil

    for _, signal in pairs(self._signals) do
        signal:destroy()
    end

    self.destroyed = true
end

--[=[
    Sends a request to the server and yields until it receives a response

    @param ... any
    @return any
]=]
function RemoteFunctionClient:invokeServer(...)
    local args = {prepArgs(...)}

    if self._server._remoteFunctions[self.name] then
        return self._server:getRemoteFunction(self.name):_invokeServer(self._client, table.unpack(args))
    end
end

--[=[
    PascalCase alias for invokeServer

    @param ... any
    @return any

    @yields

    @method InvokeServer
    @within RemoteFunctionClient
]=]
RemoteFunctionClient.InvokeServer = RemoteFunctionClient.invokeServer

return RemoteFunctionClient