##
## Licensed to the Apache Software Foundation (ASF) under one
## or more contributor license agreements.  See the NOTICE file
## distributed with this work for additional information
## regarding copyright ownership.  The ASF licenses this file
## to you 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.
##

#set($i = $intf.name())
#set($vfname = "ValueFactory$i")
#set($intfname = "$i$suffix")
#set($clname = "Remote$intfname")

// This file automatically generated by:
//   $version
//   $now
// This file is automatically created and should not be edited!

\#include "${vfname}.h"
\#include "$inc"

using namespace $namespace;

#foreach($n in $intf.iterator())
#if($n.isMsgDir($mc))
#if(!$n.isHidden())
$clname::$n.name()AsyncResultRemote::$n.name()AsyncResultRemote($clname* base, capu::SmartPointer<EtchMailbox> mailbox)
  : #if($n.hasReturn())EtchAsyncResult<$helper.getEtchTypeName($n.type(), false)>(base->mRuntime, mailbox)#{else}EtchAsyncResultNone(base->mRuntime, mailbox)#end {
  mBase = base;
}

$clname::$n.name()AsyncResultRemote::~$n.name()AsyncResultRemote() {
}


status_t $clname::$n.name()AsyncResultRemote::mailboxStatus(EtchMailbox* mb, EtchObject* state, capu::bool_t closed) {
#if(!$n.isOneway())
  status_t status;

  if(!closed) {
    capu::SmartPointer<EtchObject> result;
    status = mBase->endcall(mb, $vfname::$n.getResultMessage().vname($helper), result);
    if(status != ETCH_OK) {
      capu::SmartPointer<EtchRuntimeException> exception = new EtchRuntimeException("Error occured while reading peers answer from mailbox for call $n.name() ", ETCH_ERROR);
      setException(capu::smartpointer_cast<EtchException>(exception));
      mMailbox = NULL;
      return ETCH_ERROR;
    }
    
    //result is NULL if it was a void call and no exception has been set
    if (result.get() != NULL) {
      if(result->isInstanceOf(EtchException::TYPE())) {
        setException(result);
      }
#if($n.hasReturn())
      else {
        setResult(result);
      }
#end
    } else {
      setMailboxStatus();
    } 
  } else {
    //mailbox has been closed without answer from peer
    capu::SmartPointer<EtchRuntimeException> exception = new EtchRuntimeException("Peer did not answer in time to call $n.name()", ETCH_TIMEOUT);
    setException(capu::smartpointer_cast<EtchException>(exception));
    mMailbox = NULL;
}

#end
  return ETCH_OK;
}

$intfname::$n.name()AsyncResultPtr $clname::$n.name()AsyncResultRemote::Begin($clname* base#set($sep = ", ")#foreach($p in $n.iterator())$sep$helper.getEtchTypeName($p.type(), true) $p.name()#end) {
  status_t status;

  capu::SmartPointer<EtchMessage> msg;
  status = base->newMessage($vfname::$n.vname( $helper ), &msg); 
  if(status != ETCH_OK) {
    $n.name()AsyncResultRemote* result = new $n.name()AsyncResultRemote(base, NULL);
    capu::SmartPointer<EtchRuntimeException> exception = new EtchRuntimeException("Unable to create message for call $n.name().", status);
    result->setException(capu::smartpointer_cast<EtchException>(exception));
    return result;
  }

#set($ObjCount = 0)
#foreach( $p in $n.iterator() )
#set($ObjCount = $ObjCount + 1)
  EtchObjectPtr obj$ObjCount = ${p.name()};
  msg->put($vfname::$p.vname($helper)(), obj$ObjCount);
#end

  capu::SmartPointer<EtchMailbox> mb = NULL;
  status = base->begincall(msg, mb);
  $n.name()AsyncResultRemote* result = new $n.name()AsyncResultRemote(base, mb);

  if(status != ETCH_OK) {
    //mailbox has been closed during send
    capu::SmartPointer<EtchRuntimeException> exception = new EtchRuntimeException("Unable to call $n.name() as connection has been closed by peer.", status);
    result->setException(capu::smartpointer_cast<EtchException>(exception));
  }

  return result;
}

#end
#end
#end


/**
 * Constructs the $clname.
 *
 * @param svc
 * @param vf
 */
#if($hasBaseClass)
$clname::$clname(EtchRuntime* runtime, EtchDeliveryService* svc, EtchValueFactory* vf, EtchStack* stack )
  : Remote${i}(runtime, svc, vf, stack) {
#else
$clname::$clname(EtchRuntime* runtime, EtchDeliveryService* svc, EtchValueFactory* vf, EtchStack* stack )
  : EtchRemoteBase(runtime, svc, vf, stack), mRuntime(runtime) {
#end
}

$clname::~$clname() {
}

#foreach($n in $intf.iterator())
#if($n.isMsgDir($mc) || $n.isMsgDirBoth())
#if(!$n.isHidden())
#if(!$methodList.contains($n.name().name()))
#set ( $addMethodListStatus = $methodList.add($n.name().name()))

#if($hasBaseClass && $n.isMsgDirBoth())
$intfname::$n.name()AsyncResultPtr $clname::$n.name()(#set( $sep = "" )#foreach( $p in $n.iterator() )$sep$helper.getEtchTypeName( $p.type(), true ) $p.name() #set( $sep = ", " )#end) {
  return Remote$i::$n.name()(#set( $sep = "" )#foreach( $p in $n.iterator() )$sep$p.name() #set( $sep = ", " )#end);
}
#else
$intfname::$n.name()AsyncResultPtr $clname::$n.name()(#set( $sep = "" )#foreach( $p in $n.iterator() )$sep$helper.getEtchTypeName( $p.type(), true ) $p.name() #set( $sep = ", " )#end) {
  $n.name()AsyncResultPtr result = $clname::$n.name()AsyncResultRemote::Begin(this#set( $sep = ", ")#foreach($p in $n.iterator())$sep$p.name()#end);
  return result;
}

#end
#end
#end
#end
#end
