//
// 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 <WSCdirTree.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSCblink.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSDdev.h>
#include <WSDcolor.h>
#include <WSCfontSet.h>
#include <WSDappDev.h>
#include <WSCsform.h>
#include <WSDfileSystem.h>

WSMFguiClassInitialize(WSCdirTree, WSCtreeList);
WSMFversion(WSCdirTree, WSCtreeList);

#define WS_DT_OPEN 1
#define WS_DT_HAS_NO_SUB 2
#define WS_DT_HAS_SUB 4
#define WS_DT_SELECTED 8

//same one exists in WSClist.cpp...
#define SELECT_STATUS "ls-selected"

WSMFpropertyValueChange( WSCdirTree, WSNiconPixmap , short,WSGIappImageSet()->getImageNo("$(WSDIR)/sys/pixmaps/bi17.xpm"));
WSMFpropertyValueChange( WSCdirTree, WSNpixmapStyle , WSCuchar,WS_DYNAMIC_PIXMAP);


WSCdirTree::WSCdirTree(WSCbase* base, char* objname):
			WSCtreeList(base, objname){

  _icon_pixmap = WSGIappImageSet()->getImageNo("$(WSDIR)/sys/pixmaps/bi16.xpm");
//  _virtual_scr = 0;
  _dir_name = WSGFstrdup("");

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCdirTree);
    WSMFpropertyCreate(WSNdirName, char*, _dir_name,WSSdirName);

    WSMFpropertyValueChangeDef( WSCdirTree,WSNiconPixmap ,short);
    WSMFpropertyValueChangeDef( WSCdirTree,WSNpixmapStyle ,WSCuchar);

  WSMFpropertyCreateEnd

}
WSMFproperty( WSCdirTree, WSNdirName,  char*, _dir_name,WSGFstrdup(""));

void WSCdirTree::setWorkWSNdirName(char* dir){
  setSelectedDirName(dir);
}
void WSCdirTree::getWorkWSNdirName(char** dir){
  long pos = getSelectedPos();
  if (pos == -1){
    delete _dir_name;
    _dir_name = WSGFstrdup("");
    *dir = _dir_name;
    return;
  }
  WSCbase* item = getLabel(pos);
  WSCstring dirname;
  dirname = item->getProperty(WSNuserString);
  if (strcmp(_dir_name,(char*)dirname)){
    delete _dir_name;
    _dir_name = WSGFstrdup((char*)dirname);
  }
  *dir = _dir_name;
}

long WSCdirTree::setSelectedDirName(char* dirname,WSCbool opened){
  if (dirname == NULL){
    return WS_ERR;
  }
#ifndef MSW
  if (dirname[0] != '/'){
    return WS_ERR;
  }
#endif  

  WSClistData dirlist;
  WSCstring tmp;
  tmp = dirname;
  long start = 1;
#ifdef MSW
  while( tmp.replaceString("\\\\","\\",0) );
  tmp.replaceString("\\","/",0);
  start = 0;
#endif
  while( tmp.replaceString("//","/",0) );

  WSCbase* item = getLabel(0);
  if ((long)item->getUserData(WS_LIST_TREE_OPEN) == 0){
    item->setUserData(WS_LIST_TREE_OPEN,(void*)1);
    item->setUserData(WS_LIST_TREE_OPEN_CH,(void*)1);
    _lb_adjust();
  }

  long i;
  long num =  tmp.getWords("/");
  long pre_pos = 0;
  for(i=start; i<num; i++){
    WSCstring lstr;
    lstr = tmp.getWord(i,"/");
    long j;
    long lnum = _lb_list.getNum();
    long fl = False;
    
    for(j=pre_pos; j<lnum; j++){
      WSCbase* item = getLabel(j);
      if (item->getVisible() == False){
        continue;
      }
      WSCstring istr;
      istr = item->getProperty(WSNlabelString);
//      if (!strcmp((char*)istr,(char*)lstr)){
      if (istr == lstr){
        fl = True;
        if (i == num -1){
          setSelectPos(j);
        }
        if (i == num -1 && opened == False){
        }else{
          if ((long)item->getUserData(WS_LIST_TREE_OPEN) == 0){
            item->setUserData(WS_LIST_TREE_OPEN,(void*)1);
            item->setUserData(WS_LIST_TREE_OPEN_CH,(void*)1);
            _lb_adjust();
          }
        }
        pre_pos = j;
        break;
      }
    }
    if (fl == False){
      _redraw_scr();
      return WS_ERR;
    }
  }
  _redraw_scr();
  return WS_NO_ERR;
}

char* WSCdirTree::getSelectedDirName(){
  long pos = getSelectedPos();
  if (pos == -1){
    delete _dir_name;
    _dir_name = WSGFstrdup("/");
    return _dir_name;
  }
  WSCbase* item = getLabel(pos);
  WSCstring dirname;
  dirname = item->getProperty(WSNuserString);
  if (strcmp(_dir_name,(char*)dirname)){
    delete _dir_name;
    _dir_name = WSGFstrdup((char*)dirname);
  }
  return _dir_name;
}


WSCdirTree::~WSCdirTree() {
  if (_dir_name != NULL){
    delete _dir_name;
  }
}

void WSCdirTree::_adjust(){
  int num = _lb_list.getNum();
//  int i;
  if (num == 0){
    _lb_adjust();
  }
  WSClist::_adjust();
}
void WSCdirTree::_lb_adjust(){
  int num = _lb_list.getNum();
  int i;
  long update = 0;
  if (num == 0){
    update = 1;
  }
  for(i=0; i<num; i++){
//printf("WSCdirTree::_lb_adjust for1 %d...\n",i);
    WSCbase* item = getLabel(i);
    if ((long)item->getUserData(WS_LIST_TREE_OPEN_CH) != 0){
      update = 1;
      break;
    }
  }
  if (update != 0){ 
//    _dir_inf.clear();
    long selected_pos = getSelectedPos();
    for(i=0; i<num; i++){
      WSCbase* item = getLabel(i);
//printf("WSCdirTree::_lb_adjust for2 %d...\n",i);
//      if (item->getVisible() != False){
        WSCstring dir;
        dir = item->getProperty(WSNuserString);
        long open = (long)item->getUserData(WS_LIST_TREE_OPEN);
        long dstatus = 0; 
        if (open == False){
        }else{
          dstatus |= WS_DT_OPEN;
        }
        if (item->getVisible() != False){
          if (selected_pos == i){
            dstatus |= WS_DT_SELECTED;
          }
          _dir_inf.setData((char*)dir,(void*)dstatus);
        }
        item->setPropertyV(WSNselectColor,(short)0);
        item->setPropertyV(WSNselectForeColor,(short)0);
        item->setUserData(SELECT_STATUS,(void*)0);
//      }
    }
//    for(i=0; i<num; i++){
//      WSCbase* item = getLabel(i);
//      item->setVisible(False); 
//    } 
    long pos = _adjust_dir("","",0,0,True);
    long num = _lb_list.getNum();
//printf("WSCdirTree::_lb_adjust pos=%d num=%d\n",pos,num);
    for(i=pos; i<num; i++){
//printf("WSCdirTree::_lb_adjust del=%d\n",i);
      delPos(pos);
    } 
  }
  WSClist::_lb_adjust();
//printf("WSCdirTree::_lb_adjust here\n");
}

long WSCdirTree::_adjust_dir(char* path,char* subdir,long level,long pos,long diropen){
//printf("WSCdirTree::_adjust_dir(%s,%s,%d,%d,%d)\n",path,subdir,level,pos,diropen);

  long lnum = _lb_list.getNum();
  if (pos < lnum){
    WSCbase* item = getLabel(pos);
    if (subdir[0] == 0){
#ifdef MSW
      item->setProperty(WSNlabelString,"My computer");
#else
      item->setProperty(WSNlabelString,"/");
#endif
    }else{
      item->setProperty(WSNlabelString,subdir);
    }
  }else{
    if (subdir[0] == 0){
#ifdef MSW
      addItem("My computer");
#else
      addItem("/");
#endif
    }else{
      addItem(subdir);
    }
  }

  setItemValue(pos,WS_INDENT_LEVEL,level);
  WSCbase* item = getLabel(pos);
  if (subdir[0] == 0){
    item->setProperty(WSNuserString,"/");
  }else{
    WSCstring path2;
    if (path[0] == '/' && path[1] == 0){
#ifdef MSW
      path2 << subdir;
#else
      path2 << "/" << subdir;
#endif
    }else{
      path2 << path << "/" << subdir;
    }
    item->setProperty(WSNuserString,(char*)path2);
  }


  pos++;
  if ( diropen != False){
    WSClistData* dir_list = NULL;
    long dstatus;
    if (subdir[0] == 0){
      dstatus = (long)_dir_inf["/"];
#ifdef MSW
      dir_list = WSGIappFileSystem()->showDir("");
#else
      dir_list = WSGIappFileSystem()->showDir("/");
#endif
    }else{
      WSCstring path2;
      if (path[0] == '/' && path[1] == 0){
#ifdef MSW
        path2 << subdir;
        dstatus = (long)_dir_inf[(char*)path2];
        if (dstatus & WS_DT_OPEN){
          dir_list = WSGIappFileSystem()->showDir((char*)path2);
        }else{
          dir_list = new WSClistData();
          dir_list->add((void*)WSGFstrdup("dir-t"));
        }
#else
        path2 << "/" << subdir;
        dstatus = (long)_dir_inf[(char*)path2];
        dir_list = WSGIappFileSystem()->showDir((char*)path2);
#endif
      }else{
        path2 << path << "/" << subdir;
        dstatus = (long)_dir_inf[(char*)path2];
        dir_list = WSGIappFileSystem()->showDir((char*)path2);
      }
//printf("dir=%s status=0x%x\n",(char*)path2,dstatus);
    }

    if (dir_list == NULL){
      return pos;
    }
    long num = dir_list->getNum();
    if (num > 0){
      int i;
      WSCstring path2;
      if (path[0] == '/' && path[1] == 0){
#ifdef MSW
        path2 << subdir;
#else
        path2 << "/" << subdir;
#endif
      }else{
        path2 << path << "/" << subdir;
      }
      long no_exec = 0; 
      if (dstatus & WS_DT_OPEN){
        item->setUserData(WS_LIST_TREE_OPEN,(void*)1);
      }else{
        item->setUserData(WS_LIST_TREE_OPEN,(void*)0);
      }
      if (dstatus & WS_DT_SELECTED){
        item->setPropertyV(WSNselectColor,(short)_select_color);
        item->setPropertyV(WSNselectForeColor,(short)_select_fore_color);
        item->setUserData(SELECT_STATUS,(void*)1);
      }
      for(i=0; i<num; i++){
//printf("WSCdirTree::_adjust_dir child for2 %d...\n",i);
        long pos2;
        char* childdir = (char*)dir_list->getData(i);
        if (no_exec != 0){
          delete childdir;
          continue;
        }
        if (dstatus & WS_DT_OPEN){
          pos2 = _adjust_dir((char*)path2,childdir,level+1,pos,True);
        }else{
          pos2 = _adjust_dir((char*)path2,childdir,level+1,pos,False);
          no_exec = 1;
        }
        pos = pos2;
        delete childdir;
      }
    }
    delete dir_list;
  }
  return pos;
}
