//
// 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 <win/WSDwinMouse.h>
#include <win/WSDwinAppDev.h>
#include <win/WSDwinformDev.h>
#include <WSCbase.h>
#include <WSCcolorSet.h>
#include <win/WSDwinColor.h>
#include <WSDfileSystem.h>
#include <WSDkeyboard.h>

//クラス情報初期化
WSMFclassInit(WSDwinMouse,WSDmouse);

WSDmouse* _winMouse_create_handler(){
  return new WSDwinMouse();
}
static long _init_mouse = 0;
class _winMouse_init{
  public: _winMouse_init(){
    _init_mouse = 1;
    WSDmouse::setCreateInstanceHandler(_winMouse_create_handler);
  };
};

_winMouse_init _winMouse_init_run_constructor;


WSDwinMouse* WSGIwinAppMouse(){
  if (_init_mouse == 0){
    _init_mouse = 1;
    WSDmouse::setCreateInstanceHandler(_winMouse_create_handler);
  }
  WSDmouse* mouse = WSGIappMouse();
  if (mouse == NULL){
    return NULL;
  }
  WSDwinMouse* winMouse =(WSDwinMouse*)mouse->cast("WSDwinMouse");
  return winMouse;

}

char* dmnames[]={
"0   IDC_ARROW",
"195 IDC_SIZENWSE",
"197 IDC_SIZENS",
"196 IDC_SIZENESW",
"176 IDC_SIZEWE",
"135 IDC_SIZENWSE",
"136 IDC_SIZENS",
"134 IDC_SIZENESW",
"163 IDC_SIZEWE",
"154 IDC_SIZEALL",
"186 IDC_SIZENS",
"182 IDC_SIZEWE",
NULL
};

WSDwinMouse::WSDwinMouse(){}
WSDwinMouse::~WSDwinMouse(){}

void WSDwinMouse::resetMouseCursors(){
  long cnt = 0;
  while(1){
    long id = getMouseCursorId(cnt);
    if (id == 0){
      cnt++;
    }else if (id > -1){
      delMouseCursor(cnt);
    }else{
      break;
    }
  }
}

void WSDwinMouse::setMouseCursor(long){}
void WSDwinMouse::initialize(){
  long num = 0;
  while(dmnames[num] != NULL){
    WSGIwinAppMouse()->setupMouseCursor(dmnames[num]);
    num++;
  };
}


void WSDwinMouse::setupMouseCursor(char* data){
  long id;
  char img1[1024];
  HCURSOR val;
WSMFtrace("WSDwinMouse::setupMouseCursor %s\n",data);
  sscanf(data,"%d %s",&id,img1);
  if (!strncmp(img1,"IDC_",4)){
    char* mstr;
    if (!strcmp("IDC_ARROW",img1)){
      mstr =IDC_ARROW;
    }else
    if (!strcmp("IDC_CROSS",img1)){
      mstr =IDC_CROSS;
    }else
    if (!strcmp("IDC_APPSTARTING",img1)){
      mstr =IDC_APPSTARTING;
    }else
    if (!strcmp("IDC_IBEAM",img1)){
      mstr =IDC_IBEAM;
    }else
    if (!strcmp("IDC_ICON",img1)){
      mstr =IDC_ICON;
    }else
    if (!strcmp("IDC_NO",img1)){
      mstr =IDC_NO;
    }else
    if (!strcmp("IDC_SIZE",img1)){
      mstr =IDC_SIZE;
    }else
    if (!strcmp("IDC_SIZEALL",img1)){
      mstr =IDC_SIZEALL;
    }else
    if (!strcmp("IDC_SIZENESW",img1)){
      mstr =IDC_SIZENESW;
    }else
    if (!strcmp("IDC_SIZENS",img1)){
      mstr =IDC_SIZENS;
    }else
    if (!strcmp("IDC_SIZENWSE",img1)){
      mstr =IDC_SIZENWSE;
    }else
    if (!strcmp("IDC_SIZEWE",img1)){
      mstr =IDC_SIZEWE;
    }else
    if (!strcmp("IDC_UPARROW",img1)){
      mstr =IDC_UPARROW;
    }else
    if (!strcmp("IDC_WAIT",img1)){
      mstr =IDC_WAIT;
    }else{
      mstr =IDC_ARROW;
    }
//    val = LoadCursor(WSGIwinAppDev()->getInstanceHandle(),mstr);
    val = LoadCursor(NULL,mstr);
WSMFtrace("WSDwinMouse::setupMouseCursor mstr=0x%x val=0x%x\n",mstr,val);
  }else{
    val = (HCURSOR)LoadImage(NULL,WSGIappFileSystem()->adjustFileName(img1),
                    IMAGE_CURSOR,0,0,LR_LOADFROMFILE);
    if (val == (HCURSOR)0){
//      val = LoadCursor(WSGIwinAppDev()->getInstanceHandle(),IDC_ARROW);
      val = LoadCursor(NULL,IDC_ARROW);
    }
  }
  addMouseCursor(id,(long)val,data);
}

long WSDwinMouse::getDefaultMouseCursor(){
static long _default_mouse = 0;
  if (_default_mouse == 0){
//    _default_mouse = (long)LoadCursor(WSGIwinAppDev()->getInstanceHandle(),IDC_ARROW);
    _default_mouse = (long)LoadCursor(NULL,IDC_ARROW);
  }
  return _default_mouse;
}

#if 0
Window WSDwinMouse::getCurrentMouseWindow(){
   int x,y,dx,dy;
   Window dr,dc;
   WSCuint ds;
   Window src = DefaultRootWindow(WSGIxwinAppDev()->display());
   while(1){
     WSCbool ret = XQueryPointer(WSGIxwinAppDev()->display(),src,
                               &dr,&dc,&dx,&dy,&x,&y,&ds);
     if (ret == False){
	   return 0;
	 }
	 if (dc == 0){
	   return src;
	 }
     src = dc;
   }
   return dc;
}
#endif

WSCbool WSDwinMouse::getMousePosition(short* ox,short* oy){
  POINT p;
  GetCursorPos(&p);
  *ox = p.x;
  *oy = p.y;
  return True;
}


WSCbool WSDwinMouse::getMousePosition(short* ox,short* oy,WSCbase* client){
  if (client != NULL){
    WSCbase* target = client;
    short diffx = 0;
    short diffy = 0;
    while(1){ 
       WSDdev* dev = target->getdev();
       if (dev == NULL){
         *ox = 0;
         *oy = 0;
         return False;
       }
       WSDwinformDev* wdev = (WSDwinformDev*)dev->cast("WSDwinformDev");
       if (wdev == NULL){
          short x;
          short y;
          client->getPropertyV(WSNx,&x);
          client->getPropertyV(WSNy,&y);
          diffx +=x;
          diffy +=y;
       }else{
         RECT r;
         GetWindowRect(wdev->getHWND(),&r);
         POINT p;
         GetCursorPos(&p);
         *ox = p.x - r.left - diffx;
         *oy = p.y - r.top - diffy;
WSMFtrace("XXZZff pt=%d,%d\n",*ox,*oy);
         break;
       }
       target = target->getParent();
     }
     
     return True;
   }
   return getMousePosition(ox,oy);
}

long WSDwinMouse::getMouseStatus(){
  long ret = getStatus();
  WSCbool fl = WSGIappKeyboard()->withShift();
  if (fl != False){
    ret |= WS_MOUSE_SHIFT;
  }
  fl = WSGIappKeyboard()->withAlt();
  if (fl != False){
    ret |= WS_MOUSE_MOD;
  }
  fl = WSGIappKeyboard()->withCntl();
  if (fl != False){
    ret |= WS_MOUSE_CONTROL;
  }
  fl = WSGIappKeyboard()->withLock();
  if (fl != False){
    ret |= WS_MOUSE_LOCK;
  }

  return ret;
}

void WSDwinMouse::setMousePosition(short x,short y){
  SetCursorPos((int)x,(int)y); 
}
HWND WSDwinMouse::getCurrentMouseWindow(){
  short x,y;
  getMousePosition(&x,&y);
  POINT p;
  p.x = x;
  p.y = y;
  return WindowFromPoint(p);
}
