//
// Copyright (C) 1999-2002 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 <unistd.h>
#include <pthread.h>
#include <nx/WSDnxPrivateTimer.h>
#include <nx/WSDnxAppDev.h>
#include <nx/WSnxcom.h>

WSMFclassInit(WSDnxPrivateTimer,WSDprivateTimer);

WSDprivateTimer* _nxPrivatetimer_create(){
  return new WSDnxPrivateTimer;
}

class _nxPrivatetimer_init {
  public: _nxPrivatetimer_init(){
    WSDprivateTimer::setCreateInstanceHandler((void*)_nxPrivatetimer_create);
  };
};

_nxPrivatetimer_init  _nxPrivatetimer_init_execute;

void* WSDnxPrivateTimer::_timer_process(void* ptr){
  WSDnxPrivateTimer* _this = (WSDnxPrivateTimer*)ptr;
  WSCulong interval_id = pthread_self();
  while(1){

    long rate = _this->_timer_rate*1000;
    usleep(rate);
    // TODO send message to the event loop.
#ifdef WS_OWN_EVENT_LOOP
    _timer_send_type* data = new _timer_send_type;
    data->timer = _this;
    data->tid = interval_id;

    WSDnxEvent ev;
    ev.type = WSEV_NX_TIMER;
    ev.data = (void*)data;
    WSGFnxSendEvent(&ev);
#endif //WS_OWN_EVENT_LOOP

    if (_this->_interval_id != (long)interval_id){
      return NULL;
    }
  }
  return NULL;
}
WSClistData WSDnxPrivateTimer::_instance_list;
WSDnxPrivateTimer::WSDnxPrivateTimer(){
  _interval_id =0;
  _instance_list.add((void*)this);
}
WSDnxPrivateTimer::~WSDnxPrivateTimer(){
  stopTimer();
  _instance_list.del((void*)this);
}
WSCbool WSDnxPrivateTimer::isValid(WSDnxPrivateTimer* inst){
  long i;
  long num = _instance_list.getNum();
  for(i=0; i<num; i++){
    WSDnxPrivateTimer* item =(WSDnxPrivateTimer*)_instance_list[i];
    if (item == inst){
      return True;
    }
  }
  return False;
}
void WSDnxPrivateTimer::startTimer(){
  _timer_on = True;
  _timer_set();
}

void WSDnxPrivateTimer::stopTimer(){
  _timer_on = False;
  if (_interval_id != 0){
    pthread_cancel(_interval_id);
    _interval_id = 0;
  }
}

void WSDnxPrivateTimer::_timer_set(){
  if (_interval_id == 0){
    pthread_t tid = 0;
    int ret = pthread_create(&tid,NULL,_timer_process,this);
    _interval_id = (long)tid;

    if (ret != 0){
dbprintf("Error. WSDnxPrivateTimer can not create thread...\n");
WSMFtrace("Error. WSDnxPrivateTimer can not create thread...\n");
      return;
    }
    pthread_detach(tid);

  }
  if ( _interval_id ==  0 ) {
dbprintf("Error. WSDnxPrivateTimer is no effective...\n");
WSMFtrace("Error. WSDnxPrivateTimer is no effective...\n");
  }
}
void WSDnxPrivateTimer::_timer_callback(WSCulong id){
  if (id != (WSCulong)_interval_id){
    return;
  }

  if (_work_proc != NULL){
    _work_proc(_data);
  }
  if (_cont != False && _timer_on == True){
  }else{
    _timer_on = False;
  }
  return;
}
