//
// 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 <WSCoption.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSDdev.h>
#include <WSCimageSet.h>
#include <WSCpopupFrame.h>
#include <WSDmouse.h>
#include <WSCfontSet.h>
#include <WSDfont.h>
#include <WSDappDev.h>
#include <WSCblink.h>
#include <WSCbaseList.h>

WSMFguiClassInitialize(WSCoption, WSCvlabel);
WSMFversion(WSCoption, WSCvlabel);

WSCoption::WSCoption(WSCbase* base, char* objname):WSCvlabel(base, objname){

  _out_side_mouse_move = True;
  _out_side_mouse_release = True;

  _menu = NULL;
  _press_state = False;
  _status_array = NULL;
  _menu_str = WSGFstrdup("");
  _value = 0;
  _shadow_type = WS_SHADOW_OUT;
  WSGIappObjectList()->addEvent(this,WSEV_GUI_POLICY_CH);

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCoption);

    WSMFpropertyCreate(WSNmenuItems, char*, _menu_str,WSSmenuItems);
    WSMFpropertyCreate(WSNvalue, long, _value,WSSvalue);

    WSMFpropertyDelete(WSNorientation);
    WSMFpropertyDelete(WSNalignmentV);
    WSMFpropertyDelete(WSNshadowType);
    WSMFpropertyDelete(WSNmaxLength);

    WSMFaddTrigger(WSEV_ACTIVATE);
    WSMFaddTrigger(WSEV_VALUE_CH);

    WSMFdelTrigger(WSEV_MOUSE_MOVE  );
    WSMFdelTrigger(WSEV_MOUSE_PRESS   );
    WSMFdelTrigger(WSEV_MOUSE_RELEASE );

  WSMFpropertyCreateEnd
}

WSMFproperty(WSCoption,WSNmenuItems,char*,_menu_str,WSGFstrdup("item1:1:ep1_name,item2:2:ep2_name,item3:3:ep3_name")); 
WSMFproperty(WSCoption, WSNvalue,      long,  _value,       0); 

void WSCoption::setWorkWSNshadowThickness(WSCuchar data){
  if (data == 0){
    setPropertyV(WSNshadowThickness,(WSCuchar)1);
  }
}

void WSCoption::setWorkWSNmenuItems(char* data){
  WSCstring str(data);  
  str.replaceString(",","\n",0);

  if (_status_array != NULL) {
    delete _status_array;
    _status_array = NULL;
  }
  long num = str.getWords("\n");    
  if (num == 0){
    _status_array = new WSCbool[1];
  }else{
    _status_array = new WSCbool[num];
  }
  long i;
//printf("WSCoption::setWorkWSNmenuItem %s num=%d %s\n",data,num,getInstanceName());
  for(i=0; i < num; i++){
    _status_array[i] = True;
    WSCstring sect = str.getWord(i,"\n");
    sect.replaceString(":","\n",0);
    long value;
    WSCstring sect_value = sect.getWord(1, "\n");
    sscanf(sect_value.getString(), "%d", &value);

    if (_value == value){
      WSCstring sect_str = sect.getWord(0, "\n");
      setPropertyV(WSNlabelString, sect_str.getString());
    }
  }
  if (_menu != NULL){
    _menu->setPropertyV(WSNmenuItems, data);
  }
}

void WSCoption::getWorkWSNmenuItems(char** ){}
void WSCoption::setWorkWSNvalue(long data){
  WSCstring str;
  if (_menu_str != NULL){
    str.setString(_menu_str);  
  }
  str.replaceString("," ,"\n", 0);

  long i;
  long num = str.getWords("\n");    
  for(i=0; i<num; i++){
    WSCstring sect = str.getWord(i, "\n");
    sect.replaceString(":", "\n", 0);

    long val = 0;
    WSCstring sect_value = sect.getWord(1, "\n");
    sscanf(sect_value.getString(), "%d", &val);

    if (val == data){
      WSCstring sect_str = sect.getWord(0, "\n");
      setPropertyV(WSNlabelString,sect_str.getString());
      return;
    }
  }
}
void WSCoption::getWorkWSNvalue(long* ){}
void WSCoption::setWorkWSNemboss(WSCbool fl ){
  if ( _menu != NULL){
    _menu->setEmboss(fl);
  }
}

WSCoption::~WSCoption(){
  WSGIappObjectList()->delEvent(this,WSEV_GUI_POLICY_CH);

  if (_menu != NULL){
    delete _menu;
  }
  if (_status_array != NULL) {
    delete _status_array;
    _status_array = NULL;
  }
  delete _menu_str;
}

long WSCoption::initialize(){
  _menu = new WSCpopupFrame(NULL, "popup-m");
  _menu->initialize();
  _menu->setInternalObject(True);
  _menu->setPropertyV(WSNx, (short)100);
  _menu->setPropertyV(WSNy, (short)100);
  _menu->setPropertyV(WSNwidth, (WSCushort)200);
  _menu->setPropertyV(WSNheight, (WSCushort)200);
  _menu->setEmboss(_emboss);


  WSCvlabel::initialize();
  setProperty(WSNmenuItems,"item1:1:ep1_name,item2:2:ep2_name,item3:3:ep3_name");
//  setProperty(WSNmenuItems,"item1:1:,item2:2:,item3:3:");
  return WS_NO_ERR;
}
long WSCoption::_device_initialize(){
  WSCvlabel::_device_initialize();
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }
  dev->setEnableEventBit( WSEV_MOUSE_MOVE_BIT | WSEV_MOUSE_OUT_BIT |
                          WSEV_MOUSE_PRESS_BIT  | WSEV_MOUSE_RELEASE_BIT );
  return WS_NO_ERR;
}

long WSCoption::draw(){
  if (getVisible() == False){
    return WS_NO_ERR;
  }
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }

  short x = _x;
  short y = _y;
  WSCushort w = _w;
  WSCushort h = _h;

  WSCbool absolute = getAbsoluteDraw();
  if (absolute == False &&  dev->isExposed(x, y, w, h) == False ){
    return WS_NO_ERR;
  }

  WSCushort st    = _shadow_thick;
  long blinking   = _bl_fl;
  long shadowtype = _shadow_type;
  long blinkfore  = WSGIappBlink()->getBlinkFore(_blink_rate);
  long blinktype  = _bl_type;
  long reverse    = _rv_fl;
  long twinblink  = _tw_fl;
  short fgno      = _fore_color;
  short bgno      = _back_color;
  short blno      = _blink_color;
  short blbgno    = _bg_blink_color;
  short tsno      = _ts_color;
  short bsno      = _bs_color;
  WSCbool bldraw  = (blinking != False && blinkfore != False);
  char  align     = getAlignment();

  if( shadowtype == WS_SHADOW_NONE &&
       bldraw && twinblink == False){
    return WS_NO_ERR;
  }

  if (WSGIappDev()->getExtGuiPolicySelected() != False){
    if (_ext_draw_proc == NULL){
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->
                               getExtGuiPolicyProc("WSCoption::draw");
    }
    if (_ext_draw_proc != NULL){
      WSCoption_draw_struct st;
      st._this = this;
      st.dev = dev;
      st.x = _x;
      st.y = _y;
      st.width = _w;
      st.height = _h;
      st.shadow_thickness = _shadow_thick;
      st.blinking = _bl_fl;
      st.blink_fore = WSGIappBlink()->getBlinkFore(_blink_rate);
      st.shadow_type = _shadow_type;
      st.blink_type  = _bl_type;
      st.twin_blink   = _tw_fl;
      st.fore_color   = _fore_color;
      st.back_color   = _back_color;
      st.blink_color  = _blink_color;
      st.back_blink_color = _bg_blink_color;
      st.top_shadow_color = _ts_color;
      st.bottom_shadow_color = _bs_color;
      st.label_string = _label_string;
      st.label_pixmap = _label_pixmap;
      st.blink_pixmap = _blink_pixmap;
      st.gradation = _grad_no;
      st.gradation_margin = _grad_margin;
      st.margin_left = _margin_left;
      st.margin_right = _margin_right;
      st.margin_top = _margin_top;
      st.margin_bottom = _margin_bottom;
      st.emboss = _emboss;
      st.font = _font;
      st.reverse_flag = _rv_fl;
      st.press_state = _press_state;

      _ext_draw_proc(&st);
      return WS_NO_ERR;
    }
  }



  long er = dev->beginDraw(x, y, w, h, absolute);
  if (er != WS_NO_ERR){
    return WS_NO_ERR;
  }

  WSCbase::update();
  setAbsoluteDraw(False);

  WSCstring  str(_label_string);
  str.replaceString("\\n", "\n", 0);

  WSCushort margin_left   = _margin_left;
  WSCushort margin_right  = _margin_right;
  WSCushort margin_top    = _margin_top;
  WSCushort margin_bottom = _margin_bottom;
  short sx = st + margin_left;
  short sy = st + margin_top;

  short sw = 0;
  if ( w > st*2 + margin_left + margin_right + 23){
    sw = w - st*2 - margin_left - margin_right - 23;
  }

  short sh = 0;
  if ( h > st*2 + margin_top + margin_bottom){
    sh = h -st*2 - margin_top - margin_bottom;
  }

  if (reverse != False) {
    if (blinktype != WS_FORE && bldraw && twinblink != False) {
      dev->setForeColor(blno);
      dev->setBackColor(blbgno);
    } else {
      dev->setForeColor(fgno);
      dev->setBackColor(bgno);
    }
  } else {
    if (blinktype != WS_FORE && bldraw && twinblink != False) {
      dev->setForeColor(blbgno);
      dev->setBackColor(blno);
    } else {
      dev->setForeColor(bgno);
      dev->setBackColor(fgno);
    }
  }
  if (_grad_no == 0){
    dev->drawFillRect(st, st, w-st*2, h-st*2);
  }else{
    dev->drawGradation(_grad_no,tsno,bgno,bsno,st, st, w-st*2, h-st*2,_grad_margin);
  }

  WSDimage* image;
  if (bldraw && blinktype != WS_BACK ){
    if (_blink_pixmap != -1 && twinblink != False){
      image = WSGIappImageSet()->getImage(_blink_pixmap);
      dev->drawImage (sx, sy, sw, sh, image, align);
    }
  }else{
    if (_label_pixmap != -1){
      image = WSGIappImageSet()->getImage(_label_pixmap);
      dev->drawImage (sx, sy, sw, sh, image, align);
    }
  }

  if (st > 0) {
    char    type = WS_SHADOW_OUT;
    if (_press_state != False) {
      type = WS_SHADOW_IN;
    }
    if (getSensitive() == False ||
       (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0)){
      type = WS_SHADOW_OUT;
    }
    WSGFdrawShadow(dev, type, st, fgno, tsno, bsno, bgno,0, 0, w, h);
  }

  if ( getSensitive() == False ||
       (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0)){
    if (_emboss != False){
      if (bldraw && blinktype != WS_BACK && twinblink != False) {
        dev->setForeColor(blno);
      } else {
        dev->setForeColor(tsno);
      }
      dev->setBackColor(bgno);
   
      if (bldraw && blinktype != WS_BACK && twinblink == False){
      }else{
        if (twinblink == False || blinking == False){
          dev->drawString(sx+1, sy+1, sw, sh, &str, _font, align, -1, False);
        }
      }
    }else{
      dev->setHatchPattern(8);
    }
  }else{
    dev->setHatchPattern(0);
  }

  if (reverse != False) {
    if (bldraw && blinktype != WS_BACK && twinblink != False) {
      dev->setForeColor(blbgno);
    } else {
      if( _emboss != False && (getSensitive() == False ||
          (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
        dev->setForeColor(bsno);
      }else{
        dev->setForeColor(bgno);
      }
    }
    dev->setBackColor(fgno);
  }else{
    if(bldraw && blinktype != WS_BACK && twinblink != False) {
      dev->setForeColor(blno);
    }else{
      if ( _emboss != False && (getSensitive() == False ||
        (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
        dev->setForeColor(bsno);
      }else{
        dev->setForeColor(fgno);
      }
    }
    dev->setBackColor(bgno);
  }
  if ( !(bldraw && blinktype != WS_BACK && twinblink == False) ){
    dev->drawString(sx, sy, sw, sh, &str, _font, align, -1, False);
  }
  if (st + 23 < w ){
    WSGFdrawShadow(dev, WS_SHADOW_OUT, 2, fgno, tsno,bsno,bgno,
                   w-23 -st, (h-7)/2, 15, 7);
  }
  dev->endDraw();
  return WS_NO_ERR;
}
void WSCoption::onVisibleChange(WSCbool fl){
  if (fl == False){
    _menu_popdown();
    _press_state = False;
  }
  WSCvlabel::onVisibleChange(fl);
}
void WSCoption::onParentVisibleChange(WSCbool fl){
  if (fl == False){
    _menu_popdown();
    _press_state = False;
  }
  WSCvlabel::onParentVisibleChange(fl);
}
void WSCoption::onMousePress(WSCpoint* point){
  if (getSensitive() == False) {
    WSCbase::onMousePress(point);
    return;
  }
  if (_press_state == False && (long)getUserData(WS_PM_POPUPED) == 0){
    if (getPropertyEditMode() == False ||
        (WSGIappMouse()->getTargetBtn() != WS_MOUSE_BTN3)){
      _menu_popup(point);
      _press_state = True;
      setAbsoluteDraw(True);
      redraw();
    }
  }
  WSCvlabel::onMousePress(point);
}

void WSCoption::onMouseRelease(WSCpoint* point){
  if (getSensitive() == False) {
    return;
  }
  if (_press_state != False){
    _menu_popdown();
    long val;
    WSCbool fl = _menu->getValue(&val);
    if (fl != False){
      if (val != _value && !(_menu_str[0] == 0 && _status_array == NULL)){
        WSCstring str(_menu_str);
        str.replaceString(",", "\n", 0);
        long i;
        long num = str.getWords("\n");    
        for (i=0; i<num; i++) {
          WSCstring sect = str.getWord(i, "\n");
          sect.replaceString(":", "\n", 0);

          long val1 = 0;
          WSCstring sect_value = sect.getWord(1, "\n");
          sscanf(sect_value.getString(), "%d", &val1);

          if (val1 == val) {
            if (_status_array[i] != False) {
              setPropertyV(WSNvalue, val);
              onValueChange(val);
              execProcedure(WSEV_VALUE_CH);
              WSCstring op_name = sect.getWord(2, "\n");
              if (strcmp(op_name.getString(),"")){
                execProcedure(op_name.getString());
              }
            }
            break;
          }
        }
      }
      if (getSensitive() != False){
        onActivate();
      }
    }
    _press_state = False;
    setAbsoluteDraw(True);
    redraw();
  }
  WSCvlabel::onMouseRelease(point);
}
void WSCoption::onMouseMove(WSCpoint*){
  if (getSensitive() == False) {
    return;
  }
  if (_press_state != False){
    _menu_update();
  } 
}
void WSCoption::onActivate(){
//  execEventProc(WSEV_ACTIVATE, NULL);
  execProcedure(WSEV_ACTIVATE);
}
long WSCoption::addProcedure(WSCprocedure* ac){
  if (existTrigger(ac->getTrigger()) == False && ac->getInternal() == False){
WSMFtrace("WSCoption::addProcedure trigger=%d not supported.\n", ac->getTrigger());
    return WS_ERR;
  }

  if (ac->getTrigger() == WSEV_ACTIVATE ){
    ac->setEffectiveTriggerMask( WSEV_MOUSE_MOVE_BIT | WSEV_MOUSE_PRESS_BIT |
                 WSEV_MOUSE_RELEASE_BIT | WSEV_MOUSE_OUT_BIT );

    _event_mask |= ac->getEffectiveTriggerMask();
    _add_prcs(&_prc_list, ac);

    WSDdev* dev = getowndev();
    if (dev != NULL){
      dev->setEnableEventBit( _event_mask );
    }
    return WS_NO_ERR;
  }
  WSCnwbase::addProcedure(ac);
  return WS_NO_ERR;
}
void WSCoption::onValueChange(long ){
}
long WSCoption::setItemSensitive(short no, WSCbool flag) {
  long ret = WS_ERR;
  if (no < 0){
    return ret;
  }

  WSCstring str(_menu_str);
  long num = str.getWords(",");

  if (no < num) {
    _status_array[no] = flag;
//printf("WSCoption::setItemSensitive no=%d fl=%d  %s\n",no,flag,getInstanceName());
    ret = WS_NO_ERR;
  }
  return(ret);
}
long WSCoption::getValue(){
  return _value;
}
WSCbool* WSCoption::getSelectStatus() {
  return _status_array;
}
long WSCoption::setSelectValue(long value, WSCbool flag){
  WSCstring str(_menu_str);
  str.replaceString(",", "\n", 0);
  long i;
  long num = str.getWords("\n");
  for (i=0; i<num; i++) {
    WSCstring sect = str.getWord(i, "\n");
    sect.replaceString(":","\n",0);
    WSCstring sect_value = sect.getWord(1, "\n");
    long val1 = 0;
    sscanf(sect_value.getString(), "%d", &val1);
    if (val1 == value) {
//printf("WSCoption::setItemSensitive no=%d fl=%d  %s\n",i,flag,getInstanceName());
      _status_array[i] = flag;
      return WS_NO_ERR;
    }
  }
  return WS_ERR;
}
void WSCoption::_menu_popup(WSCpoint* ){
  WSCushort w = _w;
  WSCushort h = _h;
  short px, py;
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return;
  }
  dev->getDispAddr(&px,&py);
  WSCuchar st = _shadow_thick;

  if (_menu != NULL && _status_array != NULL){
    short len = 0;
    short ww = 0;
    short hh = 0;
    WSCstring str(_menu_str);
    str.replaceString(",", "\n", 0);
    long num = str.getWords("\n");
    WSDfont* fn = WSGIappFontSet()->getFont(_font);
    for (short i=0; i<(short)num; i++) {
//printf("WSCoption::_menu_popup no=%d fl=%d  %s\n",i,_status_array[i],getInstanceName());
      _menu->setItemSensitive(i, _status_array[i]);
      WSCstring sect = str.getWord(i, "\n");
      sect.replaceString(":", "\n", 0);
      WSCstring sect_name = sect.getWord(0, "\n");
      if (len < (short)strlen(sect_name.getString())) {
        len = (short)strlen(sect_name.getString());
        ww = (short)fn->getStringWidth(&sect_name) + st * 2 + st * 2;
        if (w > ww) {
          ww = w;
        }
      }
    }
    hh = h * num + st * 2;

    WSCushort dispw = WSGIappDev()->getWidth();
    WSCushort disph = WSGIappDev()->getHeight();
    if (px + ww > dispw) {
      px -= (px + ww - dispw);
    }
    if (py + hh > disph) {
      py -= (py + hh - disph);
    }
    if (num > 0 && ww > 0){
      _menu->setPropertyV(WSNmenuItems, _menu_str);
      _menu->setPropertyV(WSNx, (short)(px));
      _menu->setPropertyV(WSNy, (short)(py));
      _menu->setPropertyV(WSNmenuItemHeight, h);
      _menu->setPropertyV(WSNfont, (WSCuchar)_font);
      _menu->setPropertyV(WSNforeColor, _fore_color);
      _menu->setPropertyV(WSNbackColor, _back_color);
      _menu->setPropertyV(WSNshadowThickness, st);
      _menu->setPropertyV(WSNshadowType, (char)_shadow_type);
      _menu->setPropertyV(WSNtopShadowColor, _ts_color);
      _menu->setPropertyV(WSNbottomShadowColor, _bs_color);
      _menu->setPropertyV(WSNheight, (WSCushort)(hh));
      _menu->setPropertyV(WSNwidth, (WSCushort)(ww));
      _menu->setEmboss(_emboss);
      _menu->setVisible(True);
    }
  }
}
void WSCoption::_menu_update(){
  short x, y;
  WSCbool ret = WSGIappMouse()->getMousePosition(&x, &y);
  if (ret != False){
    _menu->setAbsoluteDraw(True);
    _menu->draw();
  }
}
void WSCoption::_menu_popdown(){
  _menu->setVisible(False);
}
long WSCoption::getItemNum(){
  WSCstring str;
  str.setString(_menu_str);
  return str.getWords(",");    
}
long WSCoption::getItems(){
  return getItemNum();
}

long WSCoption::getItemValue(long pos){
  WSCstring str;
  str.setString(_menu_str);
  long num = str.getWords(",");    
  if (pos < num) {
    long value;
    WSCstring sect = str.getWord(pos,",");
    WSCstring sect_value = sect.getWord(1, ":");
    sscanf(sect_value.getString(), "%d", &value);
    return value;
  }
  return 0;
}

void(*WSCoption::_ext_draw_proc)(void*) = NULL;
WSCstring WSCoption::_policy_name;

void WSCoption::onGuiPolicyChange(long policy){
  WSCvlabel::onGuiPolicyChange(policy);
  if (WSGIappDev()->getExtGuiPolicySelected() == False){
    _ext_draw_proc = NULL;
  }else{
    if (!strcmp((char*)_policy_name,(char*)WSGIappDev()->getExtGuiPolicyName())){
    }else{
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->getExtGuiPolicyProc("WSCoption::draw");
    }
  }
  if (getVisible() != False){
    needUpdate();
    setAbsoluteDraw(True);
    redraw();
  }
}
char* WSCoption::getDefaultProperty(){
  return WSNvalue;
}
