//
// 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 <WSCballoonHelp.h>
#include <WSCclassInformation.h>
#include <WSCfontSet.h>
#include <WSDmouse.h>
#include <WSDtimer.h>
#include <WSCvlabel.h>
#include <WSDdev.h>

WSMFguiClassInitialize(WSCballoonHelp,WSCwindow);
WSMFversion(WSCballoonHelp,WSCwindow);

static void  _popup_after_secs_(WSCuchar,void* data);
static WSCballoonHelp* _the_app_balloon_help = NULL;

WSCballoonHelp* WSGIappBalloonHelp(){
  if (_the_app_balloon_help == NULL){
    _the_app_balloon_help = new WSCballoonHelp(NULL,"app-balloonhelp");
    if (_the_app_balloon_help == NULL){
      assert(0);
      return NULL;
    }else{
      _the_app_balloon_help->initialize();
    }
  }
  return _the_app_balloon_help;
};

WSCballoonHelp::WSCballoonHelp(WSCbase* base,char* objname):
                WSCwindow(base,objname){
  _bh_label = NULL;
  _bh_label_string = WSGFstrdup("");
  _font = (char)WSGIappFontSet()->getDefaultFontNo();

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCballoonHelp);
    WSMFpropertyCreate(WSNlabelString,char*, _bh_label_string,WSSlabelString  );
    WSMFpropertyCreate(WSNfont, WSCuchar, _font,WSSfont   );
    WSMFpropertyVisibleOff(WSNwidth);
    WSMFpropertyVisibleOff(WSNheight);
    WSMFpropertyVisibleOff(WSNindicatorOn);
    WSMFpropertyVisibleOff(WSNmargin);
    WSMFpropertyVisibleOff(WSNmarginLeft);
    WSMFpropertyVisibleOff(WSNemboss);
    WSMFpropertyVisibleOff(WSNbarThickness);

   WSMFpropertyCreateEnd
}

WSCballoonHelp::~WSCballoonHelp(){
  long i;
  long num = _client_list.getNum();
  for(i=0; i<num; i++){
    WSCbase* client =(WSCbase*)_client_list[i];
    client->setUserData("WSBH-RGST",(void*)0);
    _client_list.del((void*)client);

    WSCprocedure* op_mouse_in = (WSCprocedure*)client->getUserData("WSBH-MS-IN");
    client->delProcedure(op_mouse_in);
    delete op_mouse_in;
    WSCprocedure* op_mouse_out = (WSCprocedure*)client->getUserData("WSBH-MS-OUT");
    client->delProcedure(op_mouse_out);
    delete op_mouse_out;
    WSCprocedure* op_btnpress = (WSCprocedure*)client->getUserData("WSBH-BT-PRS");
    client->delProcedure(op_btnpress);
    delete op_btnpress;
    WSCprocedure* op_delete = (WSCprocedure*)client->getUserData("WSBH-DELETE");
    client->delProcedure(op_delete);
    delete op_delete;

    char* str = (char*)client->getUserData("WSBH-TITLE");
    if (str != NULL){
      delete str;
    }
  }
  delete _bh_label_string;
}

WSMFproperty( WSCballoonHelp, WSNlabelString, char*, _bh_label_string, WSGFstrdup(""));
WSMFproperty( WSCballoonHelp, WSNfont, WSCuchar, _font, (char)WSGIappFontSet()->getDefaultFontNo());

void WSCballoonHelp::setWorkWSNlabelString(char* data){
  if (_bh_label != NULL){
     _bh_label->setPropertyV(WSNlabelString,data);
  }
}
void WSCballoonHelp::getWorkWSNlabelString(char** /*data*/){}

void WSCballoonHelp::setWorkWSNfont(WSCuchar data){
  if (_bh_label != NULL){
    _bh_label->setPropertyV(WSNfont,(WSCuchar)data);
  }
}
void WSCballoonHelp::getWorkWSNfont(WSCuchar*){}

long WSCballoonHelp::initialize(){
  WSCwindow::initialize();
  setPropertyV(WSNshadowType,(char)WS_SHADOW_BORDER);
  setPropertyV(WSNshadowThickness,(WSCuchar)2);
//  setPropertyV(WSNforeColor,WSGFcolor("black"));
//  setPropertyV(WSNbackColor,WSGFcolor("gray75"));
  setPropertyV(WSNtitleBar,(char)WS_NO_MANAGE);
  setProperty(WSNindicatorOn,False);

  _bh_label = new WSCvlabel(this,"md-label");
  _bh_label->initialize();
  _bh_label->setPropertyV(WSNx,(short)1);
  _bh_label->setPropertyV(WSNy,(short)1);
//  _bh_label->setPropertyV(WSNforeColor,"black");
  _bh_label->setPropertyV(WSNforeColor,_fg_no);
  _bh_label->setPropertyV(WSNfont,(WSCuchar)_font);
  _bh_label->setPropertyV(WSNlabelString,"" );
  _bh_label->setPropertyV(WSNshadowType,(char)WS_SHADOW_TRANS);
  _bh_label->setVisible(True);
  _adjust();
  return WS_NO_ERR;
}
long WSCballoonHelp::_device_initialize(){
  WSCwindow::_device_initialize();
  WSCbool val = True;
  if (_dev != NULL){
    _dev->setValue(WSDEV_NO_FRAME,(void*)&val);
    _dev->setValue(WSDEV_FLOAT_ON_TOP,(void*)&val);
  }
  return WS_NO_ERR;
}
void WSCballoonHelp::popup(char* title,short x,short y){
  setPropertyV(WSNx,x);
  setPropertyV(WSNy,y);
  _bh_label->setPropertyV(WSNlabelString,title);
  _adjust();
  setVisible(True);
}
void WSCballoonHelp::popdown(){
  setVisible(False);
}
void WSCballoonHelp::setString(char* title){
  _bh_label->setPropertyV(WSNlabelString,title);
  _adjust();
}
long WSCballoonHelp::registerClient(WSCbase* client,char* title){
  long registered = (long)client->getUserData("WSBH-RGST");
  if (registered == 0){
    if (title == NULL){
      title = "";
    }
    _client_list.add((void*)client);

    client->setUserData("WSBH-RGST",(void*)1);
    WSCprocedure* op_mouse_in = new WSCprocedure("op_mouse_in",WSEV_MOUSE_IN);
    op_mouse_in->setInternal(True);
    op_mouse_in->setFunction(_balloon_help_popup,"_balloon_help_popup");
    op_mouse_in->setInternal(True);
    client->addProcedure(op_mouse_in);
    client->setUserData("WSBH-MS-IN",(void*)op_mouse_in);

    WSCprocedure* op_mouse_out = new WSCprocedure("op_mouse_out",WSEV_MOUSE_OUT);
    op_mouse_out->setInternal(True);
    op_mouse_out->setFunction(_balloon_help_popdown,"_balloon_help_popdown");
    op_mouse_out->setInternal(True);
    client->addProcedure(op_mouse_out);
    client->setUserData("WSBH-MS-OUT",(void*)op_mouse_out);

    WSCprocedure* op_btnpress = new WSCprocedure("op_btnpress",WSEV_MOUSE_PRESS);
    op_btnpress->setInternal(True);
    op_btnpress->setFunction(_balloon_help_popdown,"_balloon_help_popdown");
    op_btnpress->setInternal(True);
    client->addProcedure(op_btnpress);
    client->setUserData("WSBH-BT-PRS",(void*)op_btnpress);

    WSCprocedure* op_delete = new WSCprocedure("op_delete",WSEV_DELETE);
    op_delete->setInternal(True);
    op_delete->setFunction(_balloon_help_unregister,"_balloon_help_unregister");
    op_delete->setInternal(True);
    client->addProcedure(op_delete);
    client->setUserData("WSBH-DELETE",(void*)op_delete);

    client->setUserData("WSBH-INST",(void*)this);
    client->setUserData("WSBH-TITLE",(void*)WSGFstrdup(title));
    return WS_NO_ERR;
  }
  return WS_ERR;
}

long WSCballoonHelp::unregisterClient(WSCbase* client){
  long registered = (long)client->getUserData("WSBH-RGST");
  if (registered == 1){
    client->setUserData("WSBH-RGST",(void*)0);
    _client_list.del((void*)client);

    WSCprocedure* op_mouse_in = (WSCprocedure*)client->getUserData("WSBH-MS-IN");
    client->delProcedure(op_mouse_in);
    delete op_mouse_in;
    WSCprocedure* op_mouse_out = (WSCprocedure*)client->getUserData("WSBH-MS-OUT");
    client->delProcedure(op_mouse_out);
    delete op_mouse_out;
    WSCprocedure* op_btnpress = (WSCprocedure*)client->getUserData("WSBH-BT-PRS");
    client->delProcedure(op_btnpress);
    delete op_btnpress;
    WSCprocedure* op_delete = (WSCprocedure*)client->getUserData("WSBH-DELETE");
    client->delProcedure(op_delete);
    delete op_delete;

    char* str = (char*)client->getUserData("WSBH-TITLE");
    if (str != NULL){
      delete str;
    }
    return WS_NO_ERR;
  }
  return WS_ERR;
}

long WSCballoonHelp::_adjust(){
  if (_bh_label == NULL){
    return WS_NO_ERR;
  }
  WSCstring str(_bh_label->getProperty(WSNlabelString));
  WSCuchar fno;
  getPropertyV(WSNfont,&fno);
  long lines = str.getWords("\\n");
  if (lines == 1){
    lines = str.getWords("\n");
  }
  WSCushort sw = 1;
  WSCushort sh = WSGIappFontSet()->getStringHeight( fno, &str );
  if (lines == 1){
    sw = WSGIappFontSet()->getStringWidth(  fno, &str );
  }else{
    long i;
    WSCushort work;
    for(i=0; i<lines; i++){
      WSCstring line = str.getWord(i,"\\n");
      work = WSGIappFontSet()->getStringWidth(  fno, &line );
      if (sw < work){
        sw = work;
      } 
    }
    sh = sh * lines;
  }


  WSCushort dw = sw +20;
  WSCushort dh = sh +10;
  setPropertyV(WSNwidth,dw);
  setPropertyV(WSNheight,dh);
  _bh_label->setPropertyV(WSNwidth, dw );
  _bh_label->setPropertyV(WSNheight,dh );

  return WS_NO_ERR;
}
void WSCballoonHelp::_balloon_help_unregister(WSCbase* client){
  WSCballoonHelp* bhelp = (WSCballoonHelp*)client->getUserData("WSBH-INST"); 
  if (bhelp == NULL){
    return;
  }
  bhelp->unregisterClient(client);
}
void WSCballoonHelp::_balloon_help_popup(WSCbase* client){
  WSCballoonHelp* bhelp = (WSCballoonHelp*)client->getUserData("WSBH-INST"); 
  if (bhelp == NULL){
    return;
  }
  long cid = (long)client->getUserData("WSBH-CLNT-ID");
  if (cid == 0){
    bhelp->setUserData("WSBH-CLNT",(void*)client);
    long id = WSGIappTimer()->addTriggerProc(_popup_after_secs_,WS1000MS,client);
    client->setUserData("WSBH-CLNT-ID",(void*)id);
  }
}
void WSCballoonHelp::_balloon_help_popdown(WSCbase* client){
  WSCballoonHelp* bhelp = (WSCballoonHelp*)client->getUserData("WSBH-INST"); 
  if (bhelp == NULL){
    return;
  }

  WSCbase* bclient = (WSCbase*)bhelp->getUserData("WSBH-CLNT");
  long id = (long)client->getUserData("WSBH-CLNT-ID");
  if (id != 0){
    WSGIappTimer()->delTriggerProc(id);
  }

  client->setUserData("WSBH-CLNT-ID",(void*)0);
  if (bclient == client){
    bhelp->popdown();
    bhelp->update();
  }
}
static void  _popup_after_secs_(WSCuchar,void* data){
  WSCbase* client = (WSCbase*)data;
  WSCballoonHelp* bhelp = (WSCballoonHelp*)client->getUserData("WSBH-INST"); 
  if (bhelp == NULL){
    return;
  }

  bhelp->setUserData("WSBH-CLNT",(void*)client);
  short x,y;
  WSGIappMouse()->getMousePosition(&x,&y);
  x += 15;
  y += 15;

  short cx,cy;
  WSGIappMouse()->getMousePosition(&cx,&cy,client);
  short w = client->getProperty(WSNwidth);
  short h = client->getProperty(WSNheight);
  if (cx < 0 || w < cx ){
    return;
  }
  if (cy < 0 || h < cy ){
    return;
  }

  char* str = (char*)client->getUserData("WSBH-TITLE");
  if (str == NULL){
    str = "No Help";
  }

  bhelp->popup(str,x,y);
  bhelp->update();
}
