/* searchthread.hh
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2006-2024 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
 */

#ifndef SEARCHTHREAD_HH
#define SEARCHTHREAD_HH

#include "wdefines.h"
#include <string>
#include <list>
#include "aguix/thread.hh"
#include "aguix/condvar.h"
#include "nwc_dir.hh"
#include "aguix/compregex.hh"
#include "searchsettings.hh"
#include "pathtree.hh"
#include "exprfilter.hh"
#include "file_content_checker.hh"

class SearchThread : public Thread, private NWC::DirWalkCallBack
{
public:
  SearchThread( std::unique_ptr<NWC::Dir> searchdir,
                const std::string &skip_initial_dir );
  ~SearchThread();
  SearchThread( const SearchThread &other );
  SearchThread &operator=( const SearchThread &other );

  int run();

  typedef enum { SUSPENDED, SEARCHING, FINISHED } search_mode_t;
  typedef enum { STOP, SEARCH, SUSPEND } search_order_t;

  class SearchResult
  {
  public:
    SearchResult( const std::string &fullname, int linenr, bool is_dir = false );
    virtual ~SearchResult();
    
    virtual std::string getFullname() const;
    virtual int getLineNr() const;
    virtual bool getIsDir() const;
  private:
    std::string _fullname;
    int _linenr;
    bool _is_dir;
  };

  virtual void lockResults();
  virtual void unlockResults();
  virtual int getNrOfResults();
  virtual bool resultsAvailable();
  virtual SearchResult getResultLocked();  // pops result from list
    virtual size_t getExcludedEntries() const;

  virtual search_mode_t getCurrentMode();
  virtual void setOrder( search_order_t );

  virtual void setSearchSettings( const SearchSettings &sets );

  virtual std::string getCurrentActionInfo();

    virtual void setExcludePaths( const std::list< std::string > &paths );
private:
  virtual int doSearch();
  virtual bool checkName( const std::string &str );

  virtual bool checkInterrupt();

  int visit( NWC::File &file, NWC::Dir::WalkControlObj &cobj );
  int visitEnterDir( NWC::Dir &dir, NWC::Dir::WalkControlObj &cobj );
  int visitLeaveDir( NWC::Dir &dir, NWC::Dir::WalkControlObj &cobj );
  int prepareDirWalk( const NWC::Dir &dir, NWC::Dir::WalkControlObj &cobj,
                      std::list< RefCount< NWC::FSEntry > > &return_add_entries,
                      std::list< RefCount< NWC::FSEntry > > &return_skip_entries );
    void mergeResults( const std::list<SearchResult> &l1,
                       const std::list<SearchResult> &l2 );

  std::list<SearchResult> _results;
  MutEx _result_lock;
  std::list<SearchResult> m_temp_expr_filter_results;

  search_mode_t _current_mode;
  search_order_t _mode_order;
  CondVar _order_cv;

  NWC::Dir *_searchdir;
  SearchSettings m_sets;
  
  CompRegEx re;
  FileContentChecker m_content_checker;

  MutEx _current_action_lock;
  std::string _current_action;

    PathTree< bool > m_pt;

    size_t m_excluded_entries = 0;

    std::string m_skip_initial_dir;

    std::unique_ptr< ExprFilter > m_expr_filter;
};

#endif
