/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 */

#import "RemoteLayerSupport.h"

#import <objc/runtime.h>

mach_port_t RemoteLayerGetServerPort(NSString *serverName)
{
    mach_port_t theResult = MACH_PORT_NULL;
    {
        // Use reflection here so we don't have a dependency on JRSRemoteLayer.h
        Class JRSRemoteLayer_class = objc_getClass("JRSRenderServer");
        SEL recieveRenderServer_SEL = @selector(recieveRenderServer:);
        NSMethodSignature *receiveRenderServer_sig = [JRSRemoteLayer_class methodSignatureForSelector:recieveRenderServer_SEL];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:receiveRenderServer_sig];
        [invocation setSelector:recieveRenderServer_SEL];
        [invocation setTarget:JRSRemoteLayer_class];
        [invocation setArgument:&serverName atIndex:2];
        [invocation invoke];
        [invocation getReturnValue:&theResult];
    }
    return theResult;
}

id RemoteLayerGetRemoteFromLocal(mach_port_t serverPort, CALayer *localLayer)
{
    CALayer *remoteLayer = nil;
    {
        // Use reflection here so we don't have a dependency on JRSRemoteLayer.h.
        // remoteLayer = [localLayer reateRemoteLayerBoundTo:(mach_port_t)serverPort];
        SEL createRemoteLayer_SEL = @selector(createRemoteLayerBoundTo:);
        NSMethodSignature *createRemoteLayer_sig = [localLayer methodSignatureForSelector:createRemoteLayer_SEL];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:createRemoteLayer_sig];
        [invocation setSelector:createRemoteLayer_SEL];
        [invocation setArgument:&serverPort atIndex:2];
        [invocation invokeWithTarget:localLayer];
        [invocation getReturnValue:&remoteLayer];
    }
    return remoteLayer;
}

uint32_t RemoteLayerGetIdForRemote(CALayer *remoteLayer)
{
    uint32_t layerID = 0;
    {
        // Use reflection here so we don't have a dependency on JRSRemoteLayer.h.
        // layerID = [remoteLayer layerID];
        SEL layerID_SEL = @selector(layerID);
        NSMethodSignature *layerID_sig = [remoteLayer methodSignatureForSelector:layerID_SEL];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:layerID_sig];
        [invocation setSelector:layerID_SEL];
        [invocation invokeWithTarget:remoteLayer];
        [invocation getReturnValue:&layerID];
        
        // what is the purpose of these 2 calls below?
        CFRetain(remoteLayer);
        [remoteLayer release]; // GC
    }
    return layerID;
}
