/* setfilterop.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2001-2021 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "setfilterop.h"
#include "listermode.h"
#include "worker.h"
#include "aguix/acontainerbb.h"
#include "bookmarkdbproxy.hh"
#include <algorithm>
#include "workerinitialsettings.hh"
#include "nwc_path.hh"
#include "pers_string_list.hh"
#include "datei.h"
#include "worker_locale.h"
#include "aguix/cyclebutton.h"
#include "aguix/fieldlistview.h"
#include "aguix/choosebutton.h"
#include "aguix/stringgadget.h"
#include "aguix/button.h"
#include "wconfig.h"
#include "virtualdirmode.hh"

const char *SetFilterOp::name="SetFilterOp";
int SetFilterOp::instance_counter = 0;
size_t SetFilterOp::history_size = 1000;
std::unique_ptr< PersistentStringList > SetFilterOp::m_history;

class SetFilterCB : public GenericCallbackArg<void, AGMessage*>
{
public:
    SetFilterCB() : m_setfilter_op( NULL )
    {}

    SetFilterCB( SetFilterOp *setfilter_op ) : m_setfilter_op( setfilter_op )
    {
    }

    virtual ~SetFilterCB() {}
    SetFilterCB( const SetFilterCB &other );
    SetFilterCB &operator=( const SetFilterCB &rhs );

    void callback( AGMessage *msg )
    {
        if ( m_setfilter_op != NULL ) {
            m_setfilter_op->popupCallback( msg );
        }
    }

    void resetInstance()
    {
        m_setfilter_op = NULL;
    }
private:
    SetFilterOp *m_setfilter_op;
};

SetFilterOp::SetFilterOp() : FunctionProto()
{
  filtermode=INCLUDE_FILTER;
  filter = "";

  if ( instance_counter == 0 ) {
    initHistory();
  }
  instance_counter++;
  hasConfigure = true;

  m_bookmark_label = "";
  m_bookmark_filter = DirFilterSettings::SHOW_ALL;
  m_option_mode = SET_OPTION;
  m_change_filters = true;
  m_change_bookmarks = false;

  m_t_bookmark_label = "";
  m_t_bookmark_filter = DirFilterSettings::SHOW_ALL;
  m_t_option_mode = SET_OPTION;
  m_t_change_filters = true;
  m_t_change_bookmarks = false;

  m_query_label = false;
  m_t_query_label = false;

  m_popup_menu = NULL;
  m_worker = NULL;

    m_category = FunctionProto::CAT_FILELIST;

    setRequestParameters( false );
}

SetFilterOp::~SetFilterOp()
{
    cleanUpPopUp();

  instance_counter--;
  if ( instance_counter == 0 ) {
    closeHistory();
  }
}

SetFilterOp*
SetFilterOp::duplicate() const
{
  SetFilterOp *ta = new SetFilterOp();
  ta->filtermode=filtermode;
  ta->filter = filter;

  ta->m_bookmark_label = m_bookmark_label;
  ta->m_bookmark_filter = m_bookmark_filter;
  ta->m_option_mode = m_option_mode;
  ta->m_change_filters = m_change_filters;
  ta->m_change_bookmarks = m_change_bookmarks;
  ta->m_query_label = m_query_label;
  ta->setRequestParameters( requestParameters() );
  return ta;
}

bool
SetFilterOp::isName(const char *str)
{
  if(strcmp(str,name)==0) return true; else return false;
}

const char *
SetFilterOp::getName()
{
  return name;
}

int
SetFilterOp::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
  ListerMode *lm1;
  if(msg->mode!=msg->AM_MODE_DNDACTION) {
    Lister *l1 = msg->getWorker()->getActiveLister();
    if(l1!=NULL) {
      startlister=l1;
      endlister = msg->getWorker()->getOtherLister(startlister);
      lm1=startlister->getActiveMode();
      if(lm1!=NULL) {
          if(dynamic_cast< VirtualDirMode * > ( lm1 ) ) {
              normalmodesf( msg );
          } else {
              lm1->not_supported();
          }
      }
    }
  }
  return 0;
}

bool
SetFilterOp::save(Datei *fh)
{
  if ( fh == NULL ) return false;
  fh->configPutPairBool( "requestflags", requestParameters() );
  switch(filtermode) {
    case EXCLUDE_FILTER:
      fh->configPutPair( "mode", "exclude" );
      break;
    case UNSET_FILTER:
      fh->configPutPair( "mode", "unset" );
      break;
    case UNSET_ALL:
      fh->configPutPair( "mode", "unsetall" );
      break;
    default:
      fh->configPutPair( "mode", "include" );
      break;
  }
  fh->configPutPairString( "filter", filter.c_str() );

  fh->configPutPairString( "bookmarklabel", m_bookmark_label.c_str() );
  switch ( m_bookmark_filter ) {
      case DirFilterSettings::SHOW_ONLY_BOOKMARKS:
          fh->configPutPair( "bookmarkfilter", "showonlybookmarks" );
          break;
      case DirFilterSettings::SHOW_ONLY_LABEL:
          fh->configPutPair( "bookmarkfilter", "showonlylabel" );
          break;
      case DirFilterSettings::SHOW_ALL:
      default:
          fh->configPutPair( "bookmarkfilter", "showall" );
          break;
  }

  switch ( m_option_mode ) {
      case INVERT_OPTION:
          fh->configPutPair( "optionmode", "invert" );
          break;
      case SET_OPTION:
      default:
          fh->configPutPair( "optionmode", "set" );
          break;
  }
  fh->configPutPairBool( "changefilters", m_change_filters );
  fh->configPutPairBool( "changebookmarks", m_change_bookmarks );
  fh->configPutPairBool( "querylabel", m_query_label );
  return true;
}

const char *
SetFilterOp::getDescription()
{
  return catalog.getLocale(1282);
}

int
SetFilterOp::normalmodesf( ActionMessage *am )
{
    VirtualDirMode *vdm = NULL;
    ListerMode *lm1 = NULL;
    bool cont = true;

    if ( am->mode != am->AM_MODE_DNDACTION ) {
        if ( startlister == NULL ) return 1;
        lm1 = startlister->getActiveMode();
        if ( lm1 == NULL ) return 1;
    }

    if ( ! ( vdm = dynamic_cast< VirtualDirMode * >( lm1 ) ) ) {
        return 1;
    }
    
    if ( requestParameters() == true ) {
        if ( doconfigure( 1 ) != 0 ) cont = false;
    } else {
        // set values in t* variables
        tfiltermode = filtermode;
        tfilter = filter;
        
        m_t_bookmark_label = m_bookmark_label;
        m_t_bookmark_filter = m_bookmark_filter;
        m_t_option_mode = m_option_mode;
        m_t_change_filters = m_change_filters;
        m_t_change_bookmarks = m_change_bookmarks;
        m_t_query_label = m_query_label;
    }
    
    if ( cont == true ) {
        if ( m_t_change_filters == true ) {
            if ( tfiltermode == UNSET_ALL ) {
                vdm->unsetAllFilters();
            } else {
                if ( ! tfilter.empty() ) {
                    switch ( tfiltermode ) {
                        case INCLUDE_FILTER:
                            try {
                                VirtualDirMode::vdm_filter_t t1 = vdm->checkFilter( tfilter );
                                if ( t1 != VirtualDirMode::FILTER_INCLUDE ) {
                                    vdm->setFilter( tfilter, VirtualDirMode::FILTER_INCLUDE );
                                } else {
                                    vdm->setFilter( tfilter, VirtualDirMode::FILTER_UNSET );
                                }
                            } catch ( int ) {
                                vdm->setFilter( tfilter, VirtualDirMode::FILTER_INCLUDE );
                            }
                            break;
                        case EXCLUDE_FILTER:
                            try {
                                VirtualDirMode::vdm_filter_t t1 = vdm->checkFilter( tfilter );
                                if ( t1 != VirtualDirMode::FILTER_EXCLUDE ) {
                                    vdm->setFilter( tfilter, VirtualDirMode::FILTER_EXCLUDE );
                                } else {
                                    vdm->setFilter( tfilter, VirtualDirMode::FILTER_UNSET );
                                }
                            } catch ( int ) {
                                vdm->setFilter( tfilter, VirtualDirMode::FILTER_EXCLUDE );
                            }
                            break;
                        case UNSET_FILTER:
                            vdm->setFilter( tfilter, VirtualDirMode::FILTER_UNSET );
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        if ( m_t_change_bookmarks == true ) {
            if ( m_t_query_label == true ) {
                openQueryPopUp( am );
            } else {
                if ( m_t_option_mode == SET_OPTION ) {
                    vdm->setBookmarkFilter( m_t_bookmark_filter );
                    if ( m_t_bookmark_filter == DirFilterSettings::SHOW_ONLY_LABEL ) {
                        vdm->setSpecificBookmarkLabel( m_t_bookmark_label );
                    }
                } else {
                    if ( m_t_bookmark_filter == DirFilterSettings::SHOW_ONLY_LABEL &&
                         vdm->getBookmarkFilter() != m_t_bookmark_filter ) {
                        vdm->setSpecificBookmarkLabel( m_t_bookmark_label );
                    }

                    if ( vdm->getBookmarkFilter() == m_t_bookmark_filter ) {
                        vdm->setBookmarkFilter( DirFilterSettings::SHOW_ALL );
                    } else {
                        vdm->setBookmarkFilter( m_t_bookmark_filter );
                    }
                }
            }
        }
    }
    return 0;
}

int
SetFilterOp::doconfigure(int mode)
{
  AGUIX *aguix = Worker::getAGUIX();
  StringGadget *sg;
  FieldListView *lv;
  AWindow *win;
  ChooseButton *rfcb=NULL;
  CycleButton *fmcyb;
  AGMessage *msg;
  int endmode=-1;
  char *tstr;
  int i;
  int row;
  bool lvstill;
  int lastrow;
  const int cincw = AContainer::ACONT_MINH +
                    AContainer::ACONT_MINW +
                    AContainer::ACONT_MAXH;
  const int cincwnr = cincw +
                      AContainer::ACONT_NORESIZE;
  const int cfix = AContainer::ACONT_MINH +
                   AContainer::ACONT_MINW +
                   AContainer::ACONT_MAXH +
                   AContainer::ACONT_MAXW;
  const int cmin = AContainer::ACONT_MINH +
                   AContainer::ACONT_MINW;
  
  tstr=(char*)_allocsafe(strlen(catalog.getLocale(293))+strlen(getDescription())+1);
  sprintf(tstr,catalog.getLocale(293),getDescription());
  win = new AWindow( aguix, 10, 10, 10, 10, tstr, AWindow::AWINDOW_DIALOG );
  win->create();
  _freesafe(tstr);

  AContainer *ac1 = win->setContainer( new AContainer( win, 1, 6 ), true );
  ac1->setMinSpace( 5 );
  ac1->setMaxSpace( 5 );

  ac1->add( new Text( aguix, 0, 0, getDescription() ), 0, 0, cincwnr );

  AContainer *ac1_0 = ac1->add( new AContainer( win, 2, 1 ), 0, 1 );
  ac1_0->setMinSpace( 5 );
  ac1_0->setMaxSpace( 5 );
  ac1_0->add( new Text( aguix, 0, 0, catalog.getLocale( 835 ) ), 0, 0, AContainer::CO_FIX );
  CycleButton *set_mode_cycb = (CycleButton*)ac1_0->add( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, AContainer::CO_INCW );
  set_mode_cycb->addOption( catalog.getLocale( 836 ) );
  set_mode_cycb->addOption( catalog.getLocale( 837 ) );

  if ( m_option_mode == INVERT_OPTION ) {
      set_mode_cycb->setOption( 1 );
  } else {
      set_mode_cycb->setOption( 0 );
  }

  set_mode_cycb->resize( set_mode_cycb->getMaxSize(), set_mode_cycb->getHeight() );
  ac1_0->readLimits();
  
  AContainerBB *ac1_1 = (AContainerBB*)ac1->add( new AContainerBB( win, 1, 3 ), 0, 2 );
  ac1_1->setMinSpace( 5 );
  ac1_1->setMaxSpace( 5 );
  ac1_1->setBorderWidth( 5 );
  ChooseButton *pattern_cb = (ChooseButton*)ac1_1->add( new ChooseButton( aguix, 0, 0, m_change_filters,
                                                                          catalog.getLocale( 838 ), LABEL_RIGHT, 0 ), 0, 0, AContainer::CO_INCWNR );

  AContainer *ac1_1_1 = ac1_1->add( new AContainer( win, 2, 1 ), 0, 1 );
  ac1_1_1->setMinSpace( 5 );
  ac1_1_1->setMaxSpace( 5 );
  ac1_1_1->setBorderWidth( 0 );

  ac1_1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 133 ) ), 0, 0, cfix );
  fmcyb = (CycleButton*)ac1_1_1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, cincw );
  fmcyb->addOption(catalog.getLocale(191));
  fmcyb->addOption(catalog.getLocale(192));
  fmcyb->addOption(catalog.getLocale(193));
  fmcyb->addOption(catalog.getLocale(194));
  fmcyb->resize(fmcyb->getMaxSize(),fmcyb->getHeight());
  switch(filtermode) {
    case EXCLUDE_FILTER:
      fmcyb->setOption(1);
      break;
    case UNSET_FILTER:
      fmcyb->setOption(2);
      break;
    case UNSET_ALL:
      fmcyb->setOption(3);
      break;
    default:
      fmcyb->setOption(0);
  }
  ac1_1_1->readLimits();

  AContainer *ac1_2 = ac1_1->add( new AContainer( win, 3, 2 ), 0, 2 );
  ac1_2->setMinSpace( 0 );
  ac1_2->setMaxSpace( 0 );
  ac1_2->setBorderWidth( 0 );

  ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 93 ) ), 0, 1, cfix );

  if ( mode != 0 ) {
    lv = (FieldListView*)ac1_2->add( new FieldListView( aguix, 0, 0, 100,
							7 * aguix->getCharHeight(), 0 ), 2, 0, cmin );
  
    lv->setHBarState( 2 );
    lv->setVBarState( 2 );
    lv->setDisplayFocus( true );
    lv->setAcceptFocus( true );
  
    std::list< std::string > cur_history = m_history->getList();
    for ( std::list< std::string >::const_iterator it1 = cur_history.begin();
          it1 != cur_history.end();
          it1++ ) {
        row = lv->insertRow( 0 );
        lv->setText( row, 0, *it1 );
        lv->setPreColors( row, FieldListView::PRECOLOR_ONLYACTIVE );
    }
    lv->showRow( cur_history.size() - 1 );
    lv->redraw();
  } else lv = NULL;

  sg = (StringGadget*)ac1_2->add( new StringGadget( aguix, 0, 0, 100, filter.c_str(), 0 ), 2, 1, cincw );

  ac1_2->setMinWidth( 5, 1, 0 );
  ac1_2->setMaxWidth( 5, 1, 0 );

  AContainerBB *ac1_bs = (AContainerBB*)ac1->add( new AContainerBB( win, 1, 4 ), 0, 3 );
  ac1_bs->setMinSpace( 5 );
  ac1_bs->setMaxSpace( 5 );
  ac1_bs->setBorderWidth( 5 );
  ChooseButton *bookmark_cb = (ChooseButton*)ac1_bs->add( new ChooseButton( aguix, 0, 0, m_change_bookmarks,
                                                                            catalog.getLocale( 839 ), LABEL_RIGHT, 0 ), 0, 0, AContainer::CO_INCWNR );

  AContainer *ac1_bs_1 = ac1_bs->add( new AContainer( win, 2, 1 ), 0, 1 );
  ac1_bs_1->setMinSpace( 5 );
  ac1_bs_1->setMaxSpace( 5 );
  ac1_bs_1->setBorderWidth( 0 );
  ac1_bs_1->add( new Text( aguix, 0, 0, catalog.getLocale( 840 ) ), 0, 0, AContainer::CO_FIX );
  CycleButton *bookmark_filter_cycb = (CycleButton*)ac1_bs_1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, AContainer::CO_INCW );
  bookmark_filter_cycb->addOption( catalog.getLocale( 841 ) );
  bookmark_filter_cycb->addOption( catalog.getLocale( 842 ) );
  bookmark_filter_cycb->addOption( catalog.getLocale( 843 ) );
  switch ( m_bookmark_filter ) {
      case DirFilterSettings::SHOW_ONLY_BOOKMARKS:
          bookmark_filter_cycb->setOption( 1 );
          break;
      case DirFilterSettings::SHOW_ONLY_LABEL:
          bookmark_filter_cycb->setOption( 2 );
          break;
      case DirFilterSettings::SHOW_ALL:
      default:
          bookmark_filter_cycb->setOption( 0 );
          break;
  }
  bookmark_filter_cycb->resize( bookmark_filter_cycb->getMaxSize(),
                                bookmark_filter_cycb->getHeight() );
  ac1_bs_1->readLimits();

  AContainer *ac1_bs_2 = ac1_bs->add( new AContainer( win, 3, 2 ), 0, 2 );
  ac1_bs_2->setMinSpace( 0 );
  ac1_bs_2->setMaxSpace( 0 );
  ac1_bs_2->setBorderWidth( 0 );

  ac1_bs_2->setMinWidth( 5, 1, 0 );
  ac1_bs_2->setMaxWidth( 5, 1, 0 );

  ac1_bs_2->add( new Text( aguix, 0, 0, catalog.getLocale( 844 ) ), 0, 1, AContainer::CO_FIX );
  
  FieldListView *label_lv = (FieldListView*)ac1_bs_2->add( new FieldListView( aguix,
                                                                              0, 0,
                                                                              40, 40, 0 ),
                                                           2, 0, AContainer::CO_MIN );
  label_lv->setHBarState( 2 );
  label_lv->setVBarState( 2 );

  std::list<std::string> cats = Worker::getBookmarkDBInstance().getCats();
  const std::map<std::string, WConfig::ColorDef::label_colors_t> labels = wconfig->getColorDefs().getLabelColors();
  std::map<std::string, WConfig::ColorDef::label_colors_t>::const_iterator label_it;
  
  for ( label_it = labels.begin(); label_it != labels.end(); ++label_it ) {
      if ( std::find( cats.begin(), cats.end(),
                      label_it->first ) == cats.end() ) {
          cats.push_back( label_it->first );
      }
  }
  if ( m_bookmark_label.length() > 0 && std::find( cats.begin(), cats.end(),
                                                   m_bookmark_label ) == cats.end() ) {
      cats.push_back( m_bookmark_label );
  }
  for ( std::list<std::string>::iterator it1 = cats.begin();
        it1 != cats.end();
        ++it1 ) {
      int label_row = label_lv->addRow();
      label_lv->setText( label_row, 0, *it1 );
      label_lv->setPreColors( label_row, FieldListView::PRECOLOR_ONLYACTIVE );
  }
  label_lv->resize( label_lv->getWidth(), 6 * aguix->getCharHeight() );
  ac1_bs_2->readLimits();

  StringGadget *bookmark_label_sg = (StringGadget*)ac1_bs_2->add( new StringGadget( aguix, 0, 0, 100,
                                                                                    m_bookmark_label.c_str(), 0 ), 2, 1, AContainer::CO_INCW );

  ChooseButton *query_label_cb = (ChooseButton*)ac1_bs->add( new ChooseButton( aguix, 0, 0, m_query_label,
                                                                               catalog.getLocale( 850 ), LABEL_RIGHT, 0 ), 0, 3, AContainer::CO_INCWNR );

  if(mode==0) {
    rfcb = (ChooseButton*)ac1->add( new ChooseButton( aguix, 0, 0, 20, 20,( requestParameters() == true ) ? 1 : 0,
						      catalog.getLocale( 294 ), LABEL_RIGHT, 0 ), 0, 4, cincwnr );
  }

  AContainer *ac1_3 = ac1->add( new AContainer( win, 2, 1 ), 0, 5 );
  ac1_3->setMinSpace( 5 );
  ac1_3->setMaxSpace( -1 );
  ac1_3->setBorderWidth( 0 );
  Button *okb =(Button*)ac1_3->add( new Button( aguix,
                                                0,
                                                0,
                                                catalog.getLocale( 11 ),
                                                0 ), 0, 0, cfix );
  Button *cb = (Button*)ac1_3->add( new Button( aguix,
						0,
						0,
						catalog.getLocale( 8 ),
						0 ), 1, 0, cfix );
  
  fmcyb->takeFocus();
  win->setDoTabCycling( true );
  win->contMaximize( true );
  win->show();
  lastrow = -1;
  lvstill = false;
  for(;endmode==-1;) {
    msg=aguix->WaitMessage(win);
    if(msg!=NULL) {
      switch(msg->type) {
        case AG_CLOSEWINDOW:
          if(msg->closewindow.window==win->getWindow()) endmode=1;
          break;
        case AG_BUTTONCLICKED:
          if(msg->button.button==okb) endmode=0;
          else if(msg->button.button==cb) endmode=1;
          break;
        case AG_KEYPRESSED:
          if ( win->isParent( msg->key.window, false ) == true ) {
            switch(msg->key.key) {
              case XK_1:
                i=fmcyb->getSelectedOption()+1;
                if(i>=4) i=0;
                fmcyb->setOption(i);
                break;
              case XK_2:
                sg->activate();
                break;
              case XK_3:
                if(rfcb!=NULL) rfcb->setState((rfcb->getState()==true)?false:true);
                break;
              case XK_Return:
                if ( cb->getHasFocus() == false ) {
                  endmode=0;
                }
                break;
              case XK_Escape:
                endmode=1;
                break;
              case XK_Up:
                if ( lv != NULL ) {
                  if ( sg->isActive() == true ) {
                    lv->setActiveRow( lv->getElements() - 1 );
                    lv->takeFocus();
                    lv->showActive();
                    lastrow = lv->getActiveRow();
                    sg->setText( lv->getText( lastrow, 0 ).c_str() );
                  }
                }
                lvstill = false;
                break;
              case XK_Down:
                if ( lv != NULL ) {
                  if ( lv->getHasFocus() == true ) {
                    if ( ( lv->getActiveRow() == ( lv->getElements() - 1 ) ) &&
                       ( lvstill == true ) ) {
                      lv->setActiveRow( -1 );
                      sg->takeFocus();
                    }
                  }
                }
                break;
            }
          }
          break;
        case AG_STRINGGADGET_CONTENTCHANGE:
            if ( msg->stringgadget.sg == bookmark_label_sg ) {
                bookmark_filter_cycb->setOption( 2 );
            }
            break;
        case AG_FIELDLV_ONESELECT:
        case AG_FIELDLV_MULTISELECT:
            if ( msg->fieldlv.lv == label_lv ) {
                int label_row = label_lv->getActiveRow();
                if ( label_lv->isValidRow( label_row ) == true ) {
                    bookmark_label_sg->setText( label_lv->getText( label_row, 0 ).c_str() );
                }
                bookmark_filter_cycb->setOption( 2 );
            } else if ( lv != NULL && msg->fieldlv.lv == lv ) {
                row = lv->getActiveRow();
                if ( row == lastrow ) lvstill = true;
                else lvstill = false;
                lastrow = row;
                if ( lv->isValidRow( row ) == true ) {
                    sg->setText( lv->getText( row, 0 ).c_str() );
                }
            }
          break;
      }
      aguix->ReplyMessage(msg);
    }
  }
  
  if(endmode==0) {
    // ok
    if(mode==1) {
      // store in t-variables
      tfilter = sg->getText();
      addHistoryItem( tfilter );
      switch(fmcyb->getSelectedOption()) {
        case 1:
          tfiltermode=EXCLUDE_FILTER;
          break;
        case 2:
          tfiltermode=UNSET_FILTER;
          break;
        case 3:
          tfiltermode=UNSET_ALL;
          break;
        default:
          tfiltermode=INCLUDE_FILTER;
          break;
      }

      m_t_bookmark_label = bookmark_label_sg->getText();

      switch ( bookmark_filter_cycb->getSelectedOption() ) {
          case 1:
              m_t_bookmark_filter = DirFilterSettings::SHOW_ONLY_BOOKMARKS;
              break;
          case 2:
              m_t_bookmark_filter = DirFilterSettings::SHOW_ONLY_LABEL;
              break;
          case 0:
          default:
              break;
              m_t_bookmark_filter = DirFilterSettings::SHOW_ALL;
      }

      if ( set_mode_cycb->getSelectedOption() == 1 ) {
          m_t_option_mode = INVERT_OPTION;
      } else {
          m_t_option_mode = SET_OPTION;
      }
      m_t_change_filters = pattern_cb->getState();
      m_t_change_bookmarks = bookmark_cb->getState();
      m_t_query_label = query_label_cb->getState();
    } else {
      // store in normal variables
      setRequestParameters( rfcb->getState() );
      filter = sg->getText();
      switch(fmcyb->getSelectedOption()) {
        case 1:
          filtermode=EXCLUDE_FILTER;
          break;
        case 2:
          filtermode=UNSET_FILTER;
          break;
        case 3:
          filtermode=UNSET_ALL;
          break;
        default:
          filtermode=INCLUDE_FILTER;
          break;
      }

      m_bookmark_label = bookmark_label_sg->getText();

      switch ( bookmark_filter_cycb->getSelectedOption() ) {
          case 1:
              m_bookmark_filter = DirFilterSettings::SHOW_ONLY_BOOKMARKS;
              break;
          case 2:
              m_bookmark_filter = DirFilterSettings::SHOW_ONLY_LABEL;
              break;
          case 0:
          default:
              break;
              m_bookmark_filter = DirFilterSettings::SHOW_ALL;
      }

      if ( set_mode_cycb->getSelectedOption() == 1 ) {
          m_option_mode = INVERT_OPTION;
      } else {
          m_option_mode = SET_OPTION;
      }
      m_change_filters = pattern_cb->getState();
      m_change_bookmarks = bookmark_cb->getState();
      m_query_label = query_label_cb->getState();
    }
  }
  
  delete win;

  return endmode;
}

int
SetFilterOp::configure()
{
  return doconfigure(0);
}

void SetFilterOp::initHistory()
{
    std::string str1;

    str1 = WorkerInitialSettings::getInstance().getConfigBaseDir();
    str1 = NWC::Path::join( str1, "setfilter-history" );
    m_history = std::unique_ptr< PersistentStringList >( new PersistentStringList( str1 ) );
}

void SetFilterOp::closeHistory()
{
    m_history.reset();
}

std::list< std::string > SetFilterOp::getHistory()
{
    if ( m_history ) {
        return m_history->getList();
    }

    std::string str1;

    str1 = WorkerInitialSettings::getInstance().getConfigBaseDir();
    str1 = NWC::Path::join( str1, "setfilter-history" );
    auto h = std::unique_ptr< PersistentStringList >( new PersistentStringList( str1 ) );

    return h->getList();
}

void SetFilterOp::addHistoryItem( const std::string &str )
{
    if ( str.empty() ) return;

    if ( m_history->contains( str ) ) {
        m_history->removeEntry( str );
        m_history->pushFrontEntry( str );
    } else {
        if ( m_history->size() >= history_size ) {
            m_history->removeLast();
        }
        m_history->pushFrontEntry( str );
    }
}

void SetFilterOp::setFilter( const char *nv )
{
  if ( nv == NULL ) return;
  filter = nv;
}

void SetFilterOp::setFiltermode( setfilterop_mode nv )
{
  filtermode = nv;
}

void SetFilterOp::setOptionMode( apply_option_t v )
{
    m_option_mode = v;
}

void SetFilterOp::setBookmarkLabel( const std::string &l )
{
    m_bookmark_label = l;
}

void SetFilterOp::setBookmarkFilter( DirFilterSettings::bookmark_filter_t f )
{
    m_bookmark_filter = f;
}

void SetFilterOp::setChangeFilters( bool v )
{
    m_change_filters = v;
}

void SetFilterOp::setChangeBookmarks( bool v )
{
    m_change_bookmarks = v;
}

void SetFilterOp::setQueryLabel( bool v )
{
    m_query_label = v;
}

void SetFilterOp::popupCallback( AGMessage *msg )
{
    if ( m_worker == NULL ) return;
    if ( msg == NULL ) return;
    if ( msg->type != AG_POPUPMENU_CLICKED ) return;

    VirtualDirMode *vdm = NULL;
    ListerMode *lm1 = NULL;
  
    if ( startlister == NULL ) return;
    lm1 = startlister->getActiveMode();
    if ( lm1 == NULL ) return;

    if ( ! ( vdm = dynamic_cast< VirtualDirMode * >( lm1 ) ) ) {
        return;
    }
    
    int id = msg->popupmenu.clicked_entry_id;
    if ( m_label_id_to_action.count( id ) > 0 ) {
        switch ( m_label_id_to_action[id].type ) {
            case DirFilterSettings::SHOW_ONLY_BOOKMARKS:
                vdm->setBookmarkFilter( DirFilterSettings::SHOW_ONLY_BOOKMARKS );
                break;
            case DirFilterSettings::SHOW_ONLY_LABEL:
                vdm->setBookmarkFilter( DirFilterSettings::SHOW_ONLY_LABEL );
                vdm->setSpecificBookmarkLabel( m_label_id_to_action[id].label );
                break;
            case DirFilterSettings::SHOW_ALL:
            default:
                vdm->setBookmarkFilter( DirFilterSettings::SHOW_ALL );
                break;
        }
    }

    cleanUpPopUp();
    m_worker = NULL;
}

void SetFilterOp::openQueryPopUp( ActionMessage *am )
{
    int descr_id = 0;
    std::list<PopUpMenu::PopUpEntry> m1;

    m_label_id_to_action.clear();
    cleanUpPopUp();

    VirtualDirMode *vdm = NULL;
    ListerMode *lm1 = NULL;
  
    if ( startlister == NULL ) return;
    lm1 = startlister->getActiveMode();
    if ( lm1 == NULL ) return;

    if ( ! ( vdm = dynamic_cast< VirtualDirMode * >( lm1 ) ) ) {
        return;
    }
    
    PopUpMenu::PopUpEntry e1;
    e1.name = catalog.getLocale( 841 );

    if ( vdm->getBookmarkFilter() != DirFilterSettings::SHOW_ALL ) {
        e1.type = PopUpMenu::NORMAL;
    } else {
        e1.type = PopUpMenu::GREYED_OUT;
    }

    e1.id = descr_id++;

    m_label_id_to_action[e1.id] = query_popup_t( DirFilterSettings::SHOW_ALL, "" );

    m1.push_back( e1 );

    e1.name = catalog.getLocale( 842 );

    if ( vdm->getBookmarkFilter() != DirFilterSettings::SHOW_ONLY_BOOKMARKS ) {
        e1.type = PopUpMenu::NORMAL;
    } else {
        e1.type = PopUpMenu::GREYED_OUT;
    }

    e1.id = descr_id++;

    m_label_id_to_action[e1.id] = query_popup_t( DirFilterSettings::SHOW_ONLY_BOOKMARKS, "" );

    m1.push_back( e1 );

    e1.type = PopUpMenu::HLINE;
    m1.push_back( e1 );
    
    e1.name = catalog.getLocale( 844 );
    e1.type = PopUpMenu::HEADER;
    e1.id = descr_id++;
    m1.push_back( e1 );

    e1.type = PopUpMenu::HLINE;
    m1.push_back( e1 );
    
    std::list<std::string> cats = Worker::getBookmarkDBInstance().getCats();
    const std::map<std::string, WConfig::ColorDef::label_colors_t> labels = wconfig->getColorDefs().getLabelColors();
    std::map<std::string, WConfig::ColorDef::label_colors_t>::const_iterator labelcol_it;

    for ( std::list<std::string>::iterator it1 = cats.begin();
          it1 != cats.end();
          ++it1 ) {

        if ( vdm->getBookmarkFilter() != DirFilterSettings::SHOW_ONLY_LABEL ||
             vdm->getSpecificBookmarkLabel() != *it1 ) {
            e1.type = PopUpMenu::NORMAL;
        } else {
            e1.type = PopUpMenu::GREYED_OUT;
        }

        e1.name = *it1;
        e1.id = descr_id++;

        labelcol_it = labels.find( *it1 );
        if ( labelcol_it != labels.end() ) {
            e1.fg = labelcol_it->second.normal_fg;
            e1.bg = labelcol_it->second.normal_bg;
        } else {
            e1.fg = e1.bg = -1;
        }
        
        m_label_id_to_action[e1.id] = query_popup_t( DirFilterSettings::SHOW_ONLY_LABEL, *it1 );
        
        m1.push_back( e1 );
    }
    
    if ( vdm->getBookmarkFilter() != DirFilterSettings::SHOW_ONLY_LABEL ||
         vdm->getSpecificBookmarkLabel() != "" ) {
        e1.type = PopUpMenu::NORMAL;
    } else {
        e1.type = PopUpMenu::GREYED_OUT;
    }

    e1.name = catalog.getLocale( 848 );
    e1.fg = e1.bg = -1;
    e1.id = descr_id++;
    
    m_label_id_to_action[e1.id] = query_popup_t( DirFilterSettings::SHOW_ONLY_LABEL, "" );
    
    m1.push_back( e1 );

    m_popup_menu = new PopUpMenu( Worker::getAGUIX(), m1 );
    m_popup_menu->create();

    if ( am->getKeyAction() == false ) {
        m_popup_menu->show();
    } else {
        int tx, ty, tw, th;

        if ( vdm->queryLVDimensions( tx, ty, tw, th ) == 0 ) {
            tx += tw / 2;
            ty += th / 2;
            m_popup_menu->show( tx, ty, PopUpMenu::POPUP_CENTER_IN_POSITION );
        } else {
            m_popup_menu->show();
        }
    }

    m_setfilter_cb = RefCount<SetFilterCB>( new SetFilterCB( this ) );
    m_worker = am->getWorker();
    m_worker->registerPopUpCallback( m_setfilter_cb, NULL );
}

void SetFilterOp::cleanUpPopUp()
{
    if ( m_setfilter_cb.get() != NULL ) {
        m_setfilter_cb->resetInstance();
    }

    if ( m_worker != NULL &&
         m_setfilter_cb.get() != NULL ) {
        m_worker->unregisterPopUpCallback( m_setfilter_cb );
    }

    m_setfilter_cb = RefCount<SetFilterCB>( NULL );

    if ( m_popup_menu != NULL ) {
        delete m_popup_menu;
        m_popup_menu = NULL;
    }
}

bool SetFilterOp::isInteractiveRun() const
{
    return true;
}

void SetFilterOp::setInteractiveRun()
{
    setRequestParameters( true );
}
