//
// 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 <WScom.h>
#include <win/WSDwinDragDrop.h>
#include <win/WSDwinAppDev.h>
#include <win/WSDwinformDev.h>
#include <WSCbase.h>
#include <win/WSDwinMouse.h>

#define MAX_ARGS 10

WSMFclassInit(WSDwinDragDrop,WSDdragDrop);

static WSDdragDrop* _winDrag_drop_create_handler_(){
  return new WSDwinDragDrop;
}

class _wsd_winDragdrop_init{
  public:
    _wsd_winDragdrop_init(){
        WSDdragDrop::setCreateHandler(_winDrag_drop_create_handler_);
    };
};
static _wsd_winDragdrop_init  execute_init;

WSDwinDragDrop* WSGIwinAppDragDrop(){
  WSDdragDrop* dd = WSGIappDragDrop();
  if (dd != NULL){
    WSDwinDragDrop* xdd = (WSDwinDragDrop*)dd->cast("WSDwinDragDrop");
	return xdd;
  }else{
    return NULL;
  }
}

WSCbase* WSDwinDragDrop::_drag_client = NULL;

WSDwinDragDrop::WSDwinDragDrop(){
  _under_dragging = 0;
  _mouse_back = 0;
}

WSDwinDragDrop::~WSDwinDragDrop(){
}

void WSDwinDragDrop::executeDrop(){
  if (_under_dragging == 0){
    _drag_client = NULL;
    return;
  }
  _under_dragging = 0;

  WSCbase* drop_site = NULL;
  long num = _drop_site_list.getNum();
  long i;
  for(i=num -1; i>-1; i--){
     WSCbase* site = (WSCbase*)_drop_site_list.getData(i);
     WSDdev* dev = site->getdev();
     if (dev == NULL){
       continue;
     }
     WSDwinformDev* windev = (WSDwinformDev*)dev->cast("WSDwinformDev");
     if (windev == NULL){
       continue;
     }
     HWND w = windev->getHWND();
WSMFtrace("WSDwinDragDrop search wnd=0x%x target=0x%x  XXZZe1\n",w,WSGIwinAppMouse()->getCurrentMouseWindow());
     if (w != NULL && w == WSGIwinAppMouse()->getCurrentMouseWindow()){
WSMFtrace("WSDwinDragDrop search hit. XXZZe1\n");
       drop_site = site;
       break;
     }
  }
  if (drop_site != NULL){
    void (*hd)(WSCbase*,WSCbase*) =
       (void(*)(WSCbase*,WSCbase*))drop_site->getUserData("DROP-PROC");
    if (hd != NULL){
      hd(drop_site,_drag_client);
    }
  }
  WSDdev* dev = _drag_client->getowndev();
  WSDwinformDev* windev = (WSDwinformDev*)dev->cast("WSDwinformDev");
  if (windev == NULL){
    windev = (WSDwinformDev*)dev->getParentDev()->cast("WSDwinformDev");
  }
  if (windev != NULL){
    windev->setValue(WSDEV_MOUSE_NO,&_mouse_back);
    HCURSOR mval = (HCURSOR)WSGIappMouse()->getMouseCursor(_mouse_back);
    SetCursor(mval);
  }
}


WSCbool WSDwinDragDrop::getDragState(){
  return _under_dragging;
}

void WSDwinDragDrop::_btn_press_drag_start(WSCbase* client){
WSMFtrace("WSDwinDragDrop:: drag_start %s  XXZZe1\n",client->getInstanceName());
   WSDwinDragDrop* obj = (WSDwinDragDrop*)client->getUserData("WSDRAG-SERV");
   if (obj->_under_dragging == True){
     return;
   }
   obj->_under_dragging = True;
   _drag_client = client;

  WSDdev* dev = client->getowndev();
  WSDwinformDev* windev = (WSDwinformDev*)dev->cast("WSDwinformDev");
  if (windev == NULL){
    windev = (WSDwinformDev*)dev->getParentDev()->cast("WSDwinformDev");
  }
  if (windev != NULL){
    obj->_mouse_back = windev->getMouseNo();
    WSCushort val = 154;
    windev->setValue(WSDEV_MOUSE_NO,&val);
    HCURSOR mval = (HCURSOR)WSGIappMouse()->getMouseCursor(val);
    SetCursor(mval);
  }else{
    obj->_mouse_back = 0;
  }
}

long WSDwinDragDrop::registerDragSite(WSCbase* client,char* msg){
  WSCprocedure* ac = new WSCprocedure("WSDRAG-START",WSEV_MOUSE_PRESS);
  ac->setFunction(_btn_press_drag_start,"_btn_press_drag_start");
  client->addProcedure(ac);
  client->setUserData("WSDRAG-AC",(void*)ac);
  client->setUserData("WSDRAG-MSG",(void*)WSGFstrdup(msg));
  client->setUserData("WSDRAG-SERV",(void*)this);
  return WS_NO_ERR;
}

long WSDwinDragDrop::unregisterDragSite(WSCbase* client){
  WSCprocedure* ac = (WSCprocedure*)client->getUserData("WSDRAG-AC");
  char* msg = (char*)client->getUserData("WSDRAG-MSG");
  if (msg != NULL){
    delete msg;
  }
  client->delProcedure(ac);
  delete ac;
  client->setUserData("WSDRAG-AC",(void*)NULL);
  client->setUserData("WSDRAG-MSG",(void*)NULL);
  return WS_NO_ERR;
}

long WSDwinDragDrop::registerDropSite(WSCbase* dropc,char* msg,void(*hd)(WSCbase*,WSCbase*)){
  dropc->setUserData("WSDRAG-MSG",(void*)WSGFstrdup(msg));
  dropc->setUserData("DROP-PROC",(void*)hd);
  _drop_site_list.add((void*)dropc);

  return WS_NO_ERR;
}

long WSDwinDragDrop::unregisterDropSite(WSCbase* client){
  char* msg = (char*)client->getUserData("WSDRAG-MSG");
  if (msg != NULL){
    delete msg;
  }
  client->setUserData("WSDRAG-MSG",(void*)NULL);
  _drop_site_list.del(client);

  return WS_NO_ERR;
}

