//
// 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 <WSCvudpsocket.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSCblink.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSDdev.h>
#include <WSDcolor.h>
#include <WSCfontSet.h>
#include <WSDappDev.h>

WSMFguiClassInitialize(WSCvudpsocket, WSCngbase);
WSMFversion(WSCvudpsocket, WSCngbase);

WSCvudpsocket::WSCvudpsocket(WSCbase* base, char* objname):
			WSCngbase(base, objname){
  _read_socket = NULL;
  _write_socket = NULL;
  _addr = WSGFstrdup("");
  _port = 9001;
  _title_string.setString("UDP\nSocket");
  _timeout = 60;
  _on = False;
  _reading = False; 

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCvudpsocket);

    WSMFpropertyCreate(WSNip,      char*,   _addr,WSSip);
    WSMFpropertyCreate(WSNport,    WSCushort,   _port,WSSport);
    WSMFpropertyCreate(WSNtimeout, WSCulong,   _timeout,WSStimeout);
    WSMFpropertyCreate(WSNrunning, WSCbool,   _on,WSSrunning);
      WSMFpropertySetSelection(WSRbool3,WSRbool3D);

    WSMFaddTrigger(WSEV_ACTIVATE  );
  WSMFpropertyCreateEnd

}
WSMFproperty( WSCvudpsocket, WSNip, char*, _addr ,WSGFstrdup(""));
WSMFproperty( WSCvudpsocket, WSNport, WSCushort, _port ,9001);
WSMFproperty( WSCvudpsocket, WSNtimeout, WSCulong, _timeout ,60);
WSMFproperty( WSCvudpsocket, WSNrunning, WSCbool, _on ,False);

void WSCvudpsocket::setWorkWSNip(char* ip){
  if (_write_socket == NULL){
    _init();
//    _write_socket = WSDsocket::getNewInstance();
//    _write_socket->setIsUdp(True);
  }
  _write_socket->setDestAddr(ip); 
};
void WSCvudpsocket::getWorkWSNip(char**){};

void WSCvudpsocket::setWorkWSNport(WSCushort port){
  if (_read_socket == NULL){
    _read_socket = WSDsocket::getNewInstance();
    _read_socket->setIsUdp(True);
  }
  _read_socket->setPort(port); 
  if (_write_socket == NULL){
    _write_socket = WSDsocket::getNewInstance();
    _write_socket->setIsUdp(True);
  }
  _write_socket->setDestPort(port); 
};
void WSCvudpsocket::getWorkWSNport(WSCushort*){};

void WSCvudpsocket::setWorkWSNtimeout(WSCulong timeout){
  if (_read_socket == NULL){
    _read_socket = WSDsocket::getNewInstance();
    _read_socket->setIsUdp(True);
  }
  _read_socket->setTimeout(timeout); 
  if (_write_socket == NULL){
    _write_socket = WSDsocket::getNewInstance();
    _write_socket->setIsUdp(True);
  }
  _write_socket->setTimeout(timeout); 
};
void WSCvudpsocket::getWorkWSNtimeout(WSCulong*){};

void WSCvudpsocket::setWorkWSNrunning(WSCbool fl){
  if (getPropertyEditMode() != False){
    return;
  }
  if (fl == True){
    start();
  }else{
    stop();
  }
};
void WSCvudpsocket::getWorkWSNrunning(WSCbool*){};


void WSCvudpsocket::onActivate(){
  execProcedure(WSEV_ACTIVATE);
}

WSCvudpsocket::~WSCvudpsocket() {
  if (_read_socket != NULL){
    delete _read_socket;
    _read_socket = NULL;
  }
  if (_write_socket != NULL){
    delete _write_socket;
    _write_socket = NULL;
  }
  if (_addr != NULL){
    delete _addr;
    _addr = NULL;
  }
}
void WSCvudpsocket::_init(){
  if (_read_socket == NULL){
    _read_socket = WSDsocket::getNewInstance();
  }
  _read_socket->setIsUdp(True);
//  _read_socket->setDestAddr(_addr); 
  if (strcmp(_bind_addr,"")){
    _read_socket->setAddr((char*)_bind_addr);
  }
  _read_socket->setPort(_port); 
  _read_socket->setTimeout(_timeout); 

  if (_write_socket == NULL){
    _write_socket = WSDsocket::getNewInstance();
  }
  _write_socket->setIsUdp(True);
  _write_socket->setDestAddr(_addr); 
  _write_socket->setDestPort(_port); 
  _write_socket->setTimeout(_timeout); 
}

long WSCvudpsocket::read(WSCuchar* buffer,long size){
  if (_read_socket == NULL){
    _init();
  }
  if (_read_socket == NULL){
    return -1;
  }
  long ret =  _read_socket->read(buffer,size);
  _error_str = _read_socket->getLastError();
  return ret;
}
long WSCvudpsocket::write(WSCuchar* buffer,long size){
  if (_write_socket == NULL){
    _init();
  }
  if (_write_socket == NULL){
    return -1;
  }
  long ret = _write_socket->write(buffer,size);
  _error_str = _write_socket->getLastError();
  return ret;
}
void WSCvudpsocket::_udp_read_work(WSDsocket* sock,void* socket,WSCulong addr){
//printf("WSCvudpsocket::_udp_read_work 0x%x 0x%x\n",sock,socket);
  WSCvudpsocket* _this = (WSCvudpsocket*)sock->getUserData();
//printf("WSCvudpsocket::_udp_read_work _this 0x%x\n",_this);
  _this->onActivate();
  _this->_read_socket->_continue_udp_read_accept();
}
long WSCvudpsocket::start(){
  _init();
  if (_read_socket == NULL){
    return WS_NO_ERR;
  }
  if (_reading == False){
    _reading = True;
    _read_socket->setUserData(this);
    return _read_socket->acceptEx(_udp_read_work);
  }
  return WS_NO_ERR;
}
long WSCvudpsocket::stop(){
  if (_read_socket == NULL){
    return WS_NO_ERR;
  }
  if (_reading != False){
    _reading = False;
    return _read_socket->stopAcceptEx();
  }
  return WS_NO_ERR;
}
WSCstring WSCvudpsocket::getDestAddr(){
  if (_read_socket == NULL){
    WSCstring tmp;
    return tmp;
  }
  return _read_socket->getDestAddr();
}
void WSCvudpsocket::setBindAddr(char* addr){
  _bind_addr = addr;
}
WSCstring WSCvudpsocket::getBindAddr(){
  return _bind_addr;
}
void WSCvudpsocket::getErrorMsg(char* buffer,long size){
  if (size < 1){
    return;
  }
  strncpy(buffer,(char*)_error_str,size);
  buffer[size-1] = 0;
}
WSCstring WSCvudpsocket::getErrorMessage(){
  WSCstring ret;
  ret.setString(_error_str);
  return ret;
}


