/**
 * Copyright 2014 NAVER Corp.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.navercorp.pinpoint.plugin.arcus.interceptor;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

import net.spy.memcached.MemcachedNode;
import net.spy.memcached.ops.Operation;

import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId;
import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.SpanAsyncEventSimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Group;
import com.navercorp.pinpoint.plugin.arcus.ArcusConstants;
import com.navercorp.pinpoint.plugin.arcus.OperationAccessor;
import com.navercorp.pinpoint.plugin.arcus.ServiceCodeAccessor;

/**
 * @author emeroad
 * @author jaehong.kim
 */
@Group(ArcusConstants.ARCUS_FUTURE_SCOPE)
public class FutureGetInterceptor extends SpanAsyncEventSimpleAroundInterceptor {

    public FutureGetInterceptor(MethodDescriptor methodDescriptor, TraceContext traceContext) {
        super(traceContext, methodDescriptor);
    }

    @Override
    protected void doInBeforeTrace(SpanEventRecorder recorder, AsyncTraceId asyncTraceId, Object target, Object[] args) {
    }

    @Override
    protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
        // find the target node
        final Operation op = ((OperationAccessor)target)._$PINPOINT$_getOperation();
        if (op != null) {
            MemcachedNode handlingNode = op.getHandlingNode();
            if (handlingNode != null) {
                SocketAddress socketAddress = handlingNode.getSocketAddress();
                if (socketAddress instanceof InetSocketAddress) {
                    InetSocketAddress address = (InetSocketAddress) socketAddress;
                    recorder.recordEndPoint(address.getHostName() + ":" + address.getPort());
                }
            } else {
                logger.info("no handling node");
            }
        } else {
            logger.info("operation not found");
        }

        // determine the service type
        String serviceCode = ((ServiceCodeAccessor)op)._$PINPOINT$_getServiceCode();
        if (serviceCode != null) {
            recorder.recordDestinationId(serviceCode);
            recorder.recordServiceType(ArcusConstants.ARCUS_FUTURE_GET);
        } else {
            recorder.recordDestinationId("MEMCACHED");
            recorder.recordServiceType(ArcusConstants.MEMCACHED_FUTURE_GET);
        }

        if (op != null) {
            recorder.recordException(op.getException());
        }
        recorder.recordApi(methodDescriptor);
    }
}

@@ -212,15 +212,14 @@
 %0A * 
+%3Cp%3E
 %0A *
-    
  htt
@@ -261,16 +261,19 @@
 -2.0%0A * 
+%3Cp%3E
 %0A * Unle
@@ -2008,24 +2008,328 @@
 hrowable) %7B%0A
+        recorder.recordApi(methodDescriptor);%0A        recorder.recordDestinationId(%22MEMCACHED%22);%0A        recorder.recordServiceType(ArcusConstants.MEMCACHED_FUTURE_GET);%0A%0A        if (!(target instanceof OperationAccessor)) %7B%0A            logger.info(%22operation not found%22);%0A            return;%0A        %7D%0A%0A
         // f
@@ -2397,16 +2397,17 @@
 ccessor)
+ 
 target).
@@ -2441,33 +2441,33 @@
 %0A        if (op 
-!
+=
 = null) %7B%0A      
@@ -2456,32 +2456,158 @@
  == null) %7B%0A    
+        logger.info(%22operation is null%22);%0A            return;%0A        %7D%0A%0A        recorder.recordException(op.getException());%0A
         Memcache
@@ -2653,28 +2653,24 @@
 ();%0A        
-    
 if (handling
@@ -2697,20 +2697,16 @@
         
-   
- 
 SocketAd
@@ -2768,28 +2768,24 @@
             
-    
 if (socketAd
@@ -2838,20 +2838,16 @@
         
- 
-   
 InetSock
@@ -2901,20 +2901,16 @@
 ddress;%0A
-    
         
@@ -3007,24 +3007,18 @@
     
-    %7D%0A  
+%7D%0A
         
   %7D 
@@ -3009,26 +3009,24 @@
   %7D%0A        
-  
 %7D else %7B%0A   
@@ -3014,36 +3014,32 @@
        %7D else %7B%0A
-    
             logg
@@ -3079,90 +3079,64 @@
     
-    %7D%0A        %7D else %7B%0A            logger.info(%22operation not found%22);%0A    
+%7D%0A%0A        if (op instanceof ServiceCodeAccessor) %7B%0A
     
-%7D%0A%0A
     
@@ -3169,16 +3169,20 @@
 ce type%0A
+    
         
@@ -3224,16 +3224,17 @@
 ccessor)
+ 
 op)._$PI
@@ -3263,24 +3263,28 @@
 ();%0A        
+    
 if (serviceC
@@ -3290,32 +3290,36 @@
 Code != null) %7B%0A
+    
             reco
@@ -3365,149 +3365,8 @@
     
-        recorder.recordServiceType(ArcusConstants.ARCUS_FUTURE_GET);%0A        %7D else %7B%0A            recorder.recordDestinationId(%22MEMCACHED%22);%0A
     
@@ -3411,33 +3411,29 @@
 usConstants.
-MEMCACHED
+ARCUS
 _FUTURE_GET)
@@ -3446,154 +3446,28 @@
     
-%7D%0A%0A
     
-    if (op != null) %7B%0A            recorder.recordException(op.getException());%0A        %7D%0A        recorder.recordApi(methodDescriptor);
+%7D%0A        %7D
 %0A    %7D%0A%7D
 %0A
@@ -3465,9 +3465,8 @@
 %0A    %7D%0A%7D
-%0A

Check NPE condition.