//
// 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.

#ifndef WSCCLASSINFOMATION_H
#define WSCCLASSINFOMATION_H

#include <WScom.h>
#include <WSCproperty.h>
#include <WSClistData.h>
#include <WSCindexData.h>
#include <WSSdef.h>
#include <WSRdef.h>

class WSCclassInformation{

 private:
   WSCclassInformation* _pclass_info;
   WSClistData  _prop_list;
   WSCulong     _trigger_mask;
   WSCulong     _del_trigger_mask;
   WSClistData* _inf_table; 
   WSClistData* _all_prop_list;
   WSClistData* _prop_list_for_init;
   WSCindexData _all_ext_trigger_list;
   WSCindexData _ext_trigger_list;
   WSClistData  _del_ext_trigger_list;

   void* _bases;

   void _create_inf_table();

 public:
   char* cname;
   long  cname_hash_value;

   WSCclassInformation(char* cname,WSCclassInformation* parent);
   virtual ~WSCclassInformation();

   WSCbool      getPropObj(char* prop_name,WSCproperty** prop);
   WSCbool      getPropObj(char* prop_name,char** class_name);
   void         addPropObj(WSCproperty* prop);
   void         setTrigger(long trg); 
   void         setDelTrigger(long trg); 
   WSCbool      existTrigger(long trg);
   WSCbool      _existExtTrigger(long trg);
   WSCbool      _existTrigger(long trg);
   WSClistData* getHashTable();
   WSClistData* getAllPropertyList();
   WSClistData* getPropertyList();
   WSClistData* getPropertyListForInit();
   void*        getClassInstanceList();
   void         setClassInstanceList(void*);

   void         setExtTrigger(long trg,char* tname);
   void         setDelExtTrigger(long trg);
   WSCindexData* getExtTriggerList();
   WSCindexData* getAllExtTriggerList();

   WSCclassInformation* getParentClassInformation();
};
struct WSChashData{
   WSChashData();
   WSCclassInformation* _class_info;
   WSCproperty* _property;
};
extern WSDLEX WSCclassInformation* WSGIappClassInformation();

#define WSMFdefineUseDevice(CN,DN) \
  char* CN::getUseDevName(){return #DN;}

#define WSMFpropertyCreateStart \
  static WSCbool _prop_init = False; \
  if (_prop_init == False){ \
    _prop_init = True; \
    WSCproperty* prop; \
    prop = NULL;

#define WSMFpropertyCreate(PropName,PropType,WorkVar,BuilderTitle) \
  prop = new WSCproperty(PropName,getClassName()); \
  getClassInformation()->addPropObj(prop); \
  prop->setType( #PropType,_set_p_w ## WorkVar, _get_p_w  ## WorkVar, \
     _get_def_w ## WorkVar); \
  prop->_builder_title = BuilderTitle;
#define WSMFpropertySetSelection(ValueNameList,ValueList) \
  if (ValueNameList != NULL || ValueList != NULL){ \
    prop->setBuilderSelectValues(ValueNameList,ValueList); \
  }

#define WSMFpropertyVisibleOff(PropName) \
  prop = new WSCproperty(PropName,getClassName()); \
  prop->_ignore = True; \
  prop->_builder_visible = False; \
  getClassInformation()->addPropObj(prop);

#define WSMFpropertyInitExec(init) \
  prop->_init_execute = init;

#define WSMFpropertyVisible(Vis) \
  prop->_builder_visible = Vis;

#define WSMFpropertyFileSelect(fl) \
  prop->_file_select = fl;

#define WSMFpropertyValueChangeDef(CN,PropName,PropType) \
  prop = new WSCproperty(PropName,getClassName()); \
  getClassInformation()->addPropObj(prop); \
  prop->_default_value_change = True; \
  prop->setType( #PropType,NULL, NULL, CN ## PropName ## _get_def_w); \
  prop->_init_execute = True;

#define WSMFpropertyDelete(PropName) \
  prop = new WSCproperty(PropName,getClassName()); \
  prop->_not_use = True; \
  getClassInformation()->addPropObj(prop);

#define WSMFpropertyCreateEnd };
#define WSMFaddTrigger(TRG) getClassInformation()->setTrigger(TRG);
#define WSMFdelTrigger(TRG) getClassInformation()->setDelTrigger(TRG);
#define WSMFaddExtTrigger(TRG,TNAME) getClassInformation()->setExtTrigger(TRG,TNAME);
#define WSMFdelExtTrigger(TRG) getClassInformation()->setDelExtTrigger(TRG);
#define WSMFpropertyValueChange( CN,PN, CT, DEF ) \
  static void CN ## PN ## _get_def_w (void* var){ \
    *(CT*)var = DEF; \
  }

#define WSMFproperty(CN,PN,CT,WorkVal,DEF) \
  void CN::_get_def_w ## WorkVal(void* var){ \
    *(CT*)var = DEF; \
  } \
  void CN::_set_p_w ## WorkVal(void* ptr,void* data){ \
    CN* obj = (CN*)ptr; \
    if ( obj->WorkVal != *(CT*)data){ \
      obj->WorkVal = *(CT*)data; \
      obj->needUpdate(); \
      obj->_absolute_draw = True; \
      obj->setWork ## PN(obj->WorkVal); \
    } \
  } \
  void CN::_get_p_w ## WorkVal(void* ptr,void* data){ \
    CN* obj = (CN*)ptr; \
    CT* val = (CT*)data; \
    *val = obj->WorkVal; \
    obj->getWork ## PN(val); \
  }

#define WSMFguiClassInitialize(CN,VC) \
  static void  CN ## _save(WSDserialize*,void* ){} \
  static void  CN ## _load(WSDserialize*,void* ){} \
  static void* CN ## _create(void* ptr){ \
    WSCbase* parent = (WSCbase*)ptr; \
    CN* ret = new CN(parent,""); \
    ret->initialize(); \
    if (parent == NULL && !(ret->getObjectType() & WS_TYPE_WINDOW )){ \
      delete ret; \
      return NULL; \
    } \
    return ret; \
  } \
  static void CN ## _delete(void* ptr){ \
    WSCbase* base = (WSCbase*)ptr; \
    delete base; \
  } \
  WSMFdefineDrInheritClient(CN,VC,CN ## _save,CN ## _load, CN ## _create,CN ## _delete);\
  class CN ## _init{ \
   public: \
    CN ## _init(){ \
      WSCbase::setCreateHandler(#CN, CN::createInstance); \
    } \
    ~CN ## _init(){ \
      WSCbase::setCreateHandler(#CN, NULL); \
    } \
  }; \
  static CN ## _init _init_run_constructor; \
  WSCbase* CN ::createInstance(WSCbase* p,char* n){ \
    WSCbase* ret = new CN (p,n); \
    return ret; \
  } \
  char* CN::getClassName(){return(#CN);} \
  void* CN::cast(char *class_name){ \
    if(class_name == NULL){ \
      return(this); \
    }else if(!strcmp(class_name,#CN)){ \
      return(this); \
    }else{ \
      return(VC::cast(class_name)); \
    } \
  } \
  WSCclassInformation* CN::CN ## _info_ptr = NULL; \
  WSCclassInformation* CN::getClassInformation(){ \
    if (CN ## _info_ptr == NULL){ \
      CN ## _info_ptr = new WSCclassInformation(#CN,VC::getClassInformation()); \
    } \
    return CN ## _info_ptr; \
 }

#define WSMFversion(CN,PCN) \
  long CN::getVer(long val){return val;}; \
  long CN::checkVersion(long val){ \
    if (val/10 == CN ## _VER/10){ \
      long ret = PCN::checkVersion(PCN ## _VER); \
      if (ret == 0){ \
        WSMFtrace("Target  FILE:%s    Please recompile.\n",__FILE__); \
      } \
      return ret; \
    } \
    WSMFtrace("VERSION error. class=%s object_version=%d  <- differ -> object_version=%d\n",#CN,CN ## _VER,val); \
    fprintf(stderr,"VERSION error. class=%s object_version=%d  <- differ -> object_version=%d\n",#CN,CN ## _VER,val); \
    return 0; \
  };

#define WSMFparentCheckVerSrc(CN) \
  if (CN::checkVersion(CN ## _VER) == 0){ \
    WSMFtrace("Target CLASS:%s    Please recompile.\n",#CN); \
    fprintf(stderr,"Target CLASS:%s    Please recompile.\n",#CN); \
  }

#endif
