//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>
#include <WSCbase.h>
#include <WSCbaseList.h>
#include <WSCRbaseList.h>

WSMFclassInit(WSCRbaseList,WSCRroot);

WSCRbaseList::WSCRbaseList(){
}

WSCRbaseList::~WSCRbaseList(){
}

long WSCRbaseList::addRemoteInstanceData(WSCremoteInstanceData* idata){
  setInstanceName("tmp");
  WSCremoteCall rc;
  rc.setClassName("WSCbaseList");
  rc.setOperationName("addRemoteInstanceData");
  beginRemoteCall(&rc);
  if (_db == NULL){
//printf("WSCRbaseList::addRemoteInstancData  db=NULL\n");
    return WS_ERR;
  } 
  _db->save("WSCremoteInstanceData","inst",(void*)idata);
  long ret = WS_ERR;
  _db->load(WS_DcRLong,"ret",(void*)&ret);
  endRemoteCall();
  return ret;
}

long WSCRbaseList::delRemoteInstanceData(WSCremoteInstanceData* idata){
  setInstanceName("tmp");
  WSCremoteCall rc;
  rc.setClassName("WSCbaseList");
  rc.setOperationName("delRemoteInstanceData");
  beginRemoteCall(&rc);
  if (_db == NULL){
    return WS_ERR;
  } 
  _db->save("WSCremoteInstanceData","inst",(void*)idata);
  long ret = WS_ERR;
  _db->load(WS_DcRLong,"ret",(void*)&ret);
  endRemoteCall();
  return ret;
}
WSCremoteInstanceData* WSCRbaseList::getRemoteInstanceData(char* pn){
  setInstanceName("tmp");
  WSCremoteCall rc;
  rc.setClassName("WSCbaseList");
  rc.setOperationName("getRemoteInstanceData");
  beginRemoteCall(&rc);
  if (_db == NULL){
    return NULL;
  } 
  _db->save(WS_DcRString,"pn",(void*)pn);
  WSCremoteInstanceData* ret = NULL;
  _db->loadAlloc("WSCremoteInstanceData","ret",(void**)&ret,NULL);
  endRemoteCall();
  return ret;
}
WSCbool WSCRbaseList::checkAlive(){
  setInstanceName("tmp");
  WSCremoteCall rc;
  rc.setClassName("WSCbaseList");
  rc.setOperationName("checkAlive");
  beginRemoteCall(&rc);
  if (_db == NULL){
    return False;
  } 
  WSCbool ret;
  _db->load(WS_DcRChar,"ret",(void*)&ret);
  endRemoteCall();
  return ret;
}
short WSCRbaseList::getBindPort(){
  setInstanceName("tmp");
  WSCremoteCall rc;
  rc.setClassName("WSCbaseList");
  rc.setOperationName("getBindPort");
  beginRemoteCall(&rc);
  if (_db == NULL){
    return 0;
  } 
  short ret;
  _db->load(WS_DcRShort,"ret",(void*)&ret);
  endRemoteCall();
  return ret;
}

WSCbool _check_port_exists(short port){
  WSClistData* rlist = WSGIappObjectList()->getRemoteInstanceList();
  int i;
  int num = rlist->getNum();
  for(i=0; i<num; i++){
    WSCremoteInstanceData* rdata = (WSCremoteInstanceData*)(*rlist)[i];
    if (!strcmp("127.0.0.1",rdata->getAddr())&& rdata->getPort() == port){
      return True;
    }
  }
  return False;
}

void _WSCbaseList_remote_call(WSDserialize* db,WSCremoteCall* rc){
  if (!strcmp(rc->_op,"checkAlive")){
    WSCbool fl = True;
    db->save(WS_DcRChar,"ret",(void*)&fl);
    WSGIconductor()->clearUpdateCounter();
    return;
  }else
  if (!strcmp(rc->_op,"getBindPort")){
static WSCushort port = WS_DEFAULT_SERVER_PORT_BASE;
    port++;
    while(1){
      if (_check_port_exists(port) == False){
        break;
      }
      port++;
    }
//printf("WSCRbaseList::getBindPort return %d\n",port);
    db->save(WS_DcRUShort,"ret",(void*)&port);
    WSGIconductor()->clearUpdateCounter();
    return;
  }else
  if (!strcmp(rc->_op,"getRemoteInstanceData")){
    char* val = NULL;
    db->loadAlloc(WS_DcRString,"pn",(void**)&val,NULL);
    WSCremoteInstanceData* ret = NULL;
//printf("WSCbaseList::getRemoteInstanceData remote call.. val=0x%x\n",val);
    if (val != NULL){
//printf("WSCbaseList::getRemoteInstanceData remote call.. pinst=%s\n",(char*)val);
      ret = WSGIappObjectList()->getRemoteInstanceData(val);
      delete val;
    }
    if (ret == NULL){
      WSCremoteInstanceData ri;
      db->save("WSCremoteInstanceData","ret",(void*)&ri);
    }else{
      db->save("WSCremoteInstanceData","ret",(void*)ret);
    }
    return;
  }else
  if (!strcmp(rc->_op,"addRemoteInstanceData")){
    WSCremoteInstanceData* val = NULL;
    db->loadAlloc("WSCremoteInstanceData","inst",(void**)&val,NULL);
    long ret = WS_ERR;
    if (val != NULL){
//printf("WSCbaseList::addRemoteInstanceData remote call.. inst=%s\n",(char*)val->getPublicInstanceName());
      if (!strcmp((char*)val->getAddr(),"127.0.0.1")){
        val->setAddr(rc->_dest_addr);
      }
      ret = WSGIappObjectList()->addRemoteInstanceData(val);
      delete val;
    }
    db->save(WS_DcRLong,"ret",(void*)&ret);
    return;
  }else
  if (!strcmp(rc->_op,"delRemoteInstanceData")){
    WSCremoteInstanceData* val = NULL;
    db->loadAlloc("WSCremoteInstanceData","inst",(void**)&val,NULL);
    long ret = WS_ERR;
    if (val != NULL){
      ret = WSGIappObjectList()->addRemoteInstanceData(val);
      delete val;
    }
    db->save(WS_DcRLong,"ret",(void*)&ret);
    return;
  }

}

WSMFdefineDrNetServer(WSCbaseList,_WSCbaseList_remote_call);

