/* wpucontext.h
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2002-2023 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 WPUCONTEXT_H
#define WPUCONTEXT_H

#include "wdefines.h"
#include <string>
#include "aguix/util.h"
#include "aguix/lowlevelfunc.h"
#include "temporaryfilecache.hh"
#include "datei.h"
#include "timedtext.hh"
#include "nmextlist.hh"
#include "aguix/refcount.hh"
#include "functionproto.h"

class Worker;
class SolidButton;
class Text;
class BevelBox;
class AWindow;
class Button;

class WPUProgressCallback : public CopyfileProgressCallback
{
 public:
    WPUProgressCallback( Worker *w );
    ~WPUProgressCallback();

    callback_return_t progress_callback( loff_t current_bytes,
                                         loff_t total_bytes );

    void setCompleteFilesizes( loff_t sum );
 private:
    Worker *m_worker;
    TimedText m_text;
    time_t m_last_update;
    loff_t m_complete_sizes;
    loff_t m_bytes_already_copied;
};

class WPUStack
{
public:
  void push( const std::string &elem );
  std::string pop();
  std::string top() const;
  std::string stackEntry( int pos ) const;
  bool isEmpty() const;
  size_t size() const;
protected:
  std::vector< std::string > stack;
};

class WPUContext
{
public:
  WPUContext( Worker *, const command_list_t &coms, ActionMessage *msg );
  ~WPUContext();
    WPUContext( const WPUContext &other ) = delete;
    WPUContext &operator=( const WPUContext &other ) = delete;

    WPUContext( WPUContext &other,
                ActionMessage *msg );

  int continueAtLabel( const char *label );
  void push( int nr, std::string elem );
  std::string pop( int nr );
  std::string top( int nr );
  std::string stackEntry( int nr, int pos );
  bool isEmpty( int nr );
  int size( int nr );
  int next( std::shared_ptr< WPUContext > wpu, ActionMessage *msg );
  int openWin();
  int closeWin();

  typedef enum {
      PARSE_SUCCESS,
      PARSE_ERROR
  } parse_com_str_t;

  typedef enum {
      PERSIST_ALL,
      PERSIST_FLAGS,
      PERSIST_NOTHING
  } parse_persist_t;

  parse_com_str_t parse( const char *str1, std::string &return_str, int maxlen, bool quote, parse_persist_t persist );

  #define IFP_BUFSIZE 1024
  #define IFP_SYMTABLE_MAX 128
  
  enum ifp_t {
    IFP_NONE = -1,
    IFP_NUM = 256,
    IFP_DONE,
    IFP_ISEMPTY,
    IFP_SIZE,
    IFP_LASTERROR,
    IFP_STRING,
    IFP_TRUE,
    IFP_FALSE,
    IFP_P_AND,
    IFP_P_OR,
    IFP_E,
    IFP_NE,
    IFP_LT,
    IFP_LE,
    IFP_GT,
    IFP_GE,
    IFP_FILELISTEMPTY,
    IFP_TONUM,
    IFP_TOSTR,
    IFP_ISLOCAL
  };
  int parse_if( const char *str);
  bool filelistEmpty( bool other );
  int getLastError();
  void resetLastError();
  int getCurrentLine();
  void setRecursive( bool nv );
  bool getRecursive() const;
  void setWinProgress( int nv );
  void setWinText( const char *str );
  void setTakeDirs( bool nv );
  bool getTakeDirs() const;
  void setUseVirtualTempCopies( bool nv );
  bool getUseVirtualTempCopies() const;
  void setUseExtendedBasename( bool nv );
  bool getUseExtendedBasename() const;
  
  typedef enum { WPU_LASTERROR_STACKEMPTY = 0, WPU_LASTERROR_INVALID_STACK } wpu_lasterror_t;
  const char *getBaseDir();

  struct ifp_symentry
  {
    char *str;
    enum ifp_t token;
  };
  
    bool filelistModified( bool other, bool reset );

  std::string getTempName4File( const char *filename );

    const std::string &getPathDBFilename() const;
private:
    std::shared_ptr< std::vector< WPUStack > > m_stacks;
  command_list_t acoms;
  size_t pc;
  void buildStack( int nr );
  
  NMExtList *extlist[2];
  Worker *worker;
  ListerMode *activemode, *nonactivemode, *destmode;

  struct ifp_symentry ifp_symtable[IFP_SYMTABLE_MAX];
  char ifp_lexbuf[IFP_BUFSIZE];
  int lookahead, tokenval;

#define STRMAX 1024

  char lexemes[STRMAX];
  int lastchar;
  int lastentry;

  struct ifp_erg {
    int numval;
    char *strval;
    int wasstring;
  };

  struct ifp_erg * ifp_expr();
  struct ifp_erg * ifp_factor();
  int ifp_lookup( const char *s );
  int ifp_insert( const char *s, enum ifp_t tok );
  int ifp_lex();
  int ifp_match( int t );
  char *readBrace();
  int ifp_parse();

  const char *scanbuf;
  int scanbuflen;
  int curpos;
  int ignore;
  
  void buildExtList();
  int lasterror;

  AWindow *userwin;
  Button *cancelb;
  BevelBox *bb1, *bb2;
  SolidButton *prosb;
  Text **texts;
  int nr_of_text;
  int progress;
  
  class temp4filename_t {
  public:
    temp4filename_t()
    {
      filename = NULL;
      tempname = NULL;
    }
    ~temp4filename_t()
    {
      if ( filename != NULL ) _freesafe( filename );
      if ( tempname != NULL ) _freesafe( tempname );
    }
    temp4filename_t( const temp4filename_t &other );
    temp4filename_t &operator=( const temp4filename_t &other );
    char *filename;
    char *tempname;
    time_t modtime;
  };
  std::list<class temp4filename_t*> tempnamelist;

  std::list< TemporaryFileCache::TemporaryFileCacheEntry > m_temp_files;
  RefCount< WPUProgressCallback > m_progress_callback;
  bool m_filesizes_calculated;

  void calculateFilesizes();

  parse_com_str_t parseComStr( const char *sstr, int maxlen,
                               bool quote, std::string &return_str );
  char *StringRequest( const char *sstr, int maxlen );
    std::shared_ptr< std::vector< WPUStack > > getStacks();

  std::string m_base_dir;

  bool m_recursive;
  bool m_take_dirs;
  bool m_use_virtual_temp_copies;
  bool m_use_extended_basename;
    std::string m_pathdb_filename;
};

#endif
