/* intviewop.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2005-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 "intviewop.h"
#include "listermode.h"
#include "worker.h"
#include "ownop.h"
#include "wpucontext.h"
#include "execlass.h"
#include "fileviewer.hh"
#include "nmspecialsourceext.hh"
#include "fileentry.hh"
#include "worker_locale.h"
#include "datei.h"
#include "aguix/cyclebutton.h"
#include "aguix/button.h"
#include "aguix/choosebutton.h"
#include "aguix/stringgadget.h"
#include "aguix/awindow.h"
#include "dnd.h"

const char *InternalViewOp::name = "InternalViewOp";

InternalViewOp::InternalViewOp() : FunctionProto()
{
  _request_flags = false;
  _mode = SHOW_ACTIVE_FILE;
  _custom_files = "";
  
  hasConfigure = true;
}

InternalViewOp::~InternalViewOp()
{
}

InternalViewOp*
InternalViewOp::duplicate() const
{
  InternalViewOp *ta=new InternalViewOp();
  ta->setRequestFlags( _request_flags );
  ta->setShowFileMode( _mode );
  ta->setCustomFiles( _custom_files );
  return ta;
}

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

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

int
InternalViewOp::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
  std::string str1;
  bool cont = true;
  ListerMode *lm1 = NULL;
  std::list<std::string> filelist;

  if ( _request_flags == true ) {
    if ( doconfigure( 1 ) != 0 ) cont = false;
  } else {
    _tcustom_files = _custom_files;
    _tmode = _mode;
  }
  
  if ( cont == true ) {
    if ( msg->mode != msg->AM_MODE_DNDACTION ) {
      Lister *l1 = msg->getWorker()->getActiveLister();
      if ( l1 != NULL )
	lm1 = l1->getActiveMode();
    } else {
      lm1 = msg->dndmsg->getSourceMode();
    }
    
    if ( msg->mode == msg->AM_MODE_ONLYACTIVE )
      _tmode = SHOW_ACTIVE_FILE;
    else if ( msg->mode == msg->AM_MODE_DNDACTION ) {
        if ( msg->dndmsg->getFE() ) {
            filelist.push_back( msg->dndmsg->getFE()->fullname );
        }
    } else if ( msg->mode == msg->AM_MODE_SPECIAL ) {
        if ( msg->getFE() ) {
            filelist.push_back( msg->getFE()->fullname );
        }
    }

    if ( filelist.size() < 1 ) {
      if ( _tmode == SHOW_ACTIVE_FILE ) {
          std::list< NM_specialsourceExt > extfilelist;
          lm1->getSelFiles( extfilelist, ListerMode::LM_GETFILES_ONLYACTIVE );
          for ( auto &ss1 : extfilelist ) {
              if ( ss1.entry() ) {
                  filelist.push_back( ss1.entry()->fullname );
              }
          }
	/*} else if ( _tmode == SHOW_SELECTED_FILES ) {
	  if ( nm1 != NULL ) {
	  nm1->getSelFiles( &extfilelist, ListerMode::LM_GETFILES_SELORACT, true );
	  for ( it1 = extfilelist.begin(); it1 != extfilelist.end(); it1++ ) {
	  filelist.push_back( (*it1)->entry()->fullname );
	  }
	  NormalMode::freeSelFiles( &extfilelist );
	  }*/
      } else if ( _tmode == SHOW_CUSTOM_FILES ) {
          std::string res_str;
          if ( wpu->parse( _tcustom_files.c_str(),
                           res_str,
                           a_max( EXE_STRING_LEN - 1024, 256 ),
                           true,
                           WPUContext::PERSIST_ALL ) == WPUContext::PARSE_SUCCESS ) {
              char **argvlist;
              char *unquoted_str;
              int n, i;
	  
              n = Worker_buildArgvList( res_str.c_str(), &argvlist );
	  
              for ( i = 0; i < n; i++ ) {
                  unquoted_str = AGUIX_unquoteString( argvlist[i] );
                  filelist.push_back( unquoted_str );
                  _freesafe( unquoted_str );
              }
	  
              Worker_freeArgvList( argvlist );
          }
      }
    }

    if ( filelist.size() > 0 ) {

        for ( auto &f : filelist ) {
            msg->getWorker()->storePathPersIfInProgress( f );
        }

        FileViewer fv( msg->getWorker() );
        fv.view( filelist, NULL );
    }
  }
  return 0;
}

bool
InternalViewOp::save(Datei *fh)
{
  if ( fh == NULL ) return false;
  fh->configPutPairBool( "requestflags", _request_flags );
  fh->configPutPairString( "customfiles", _custom_files.c_str() );
  switch ( _mode ) {
    /*case SHOW_SELECTED_FILE:
      fh->configPutPair( "showmode", "selected" );
      break;*/
    case SHOW_CUSTOM_FILES:
      fh->configPutPair( "showmode", "custom" );
      break;
    default:
      fh->configPutPair( "showmode", "active" );
      break;
  }
  return true;
}

const char *
InternalViewOp::getDescription()
{
  return catalog.getLocale( 1290 );
}

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

int
InternalViewOp::doconfigure(int mode)
{
  AGUIX *aguix = Worker::getAGUIX();
  Button *okb,*cancelb, *flagb;
  AWindow *win;
  ChooseButton *rfcb=NULL;
  CycleButton *cycbm;
  StringGadget *sgcf;
  AGMessage *msg;
  int endmode=-1;
  char *tstr;
  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;
  
  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, 4 ), true );
  ac1->setMinSpace( 5 );
  ac1->setMaxSpace( 5 );

  AContainer *ac1_2 = ac1->add( new AContainer( win, 2, 1 ), 0, 0 );
  ac1_2->setMinSpace( 5 );
  ac1_2->setMaxSpace( 5 );
  ac1_2->setBorderWidth( 0 );
  ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 632 ) ), 0, 0, cfix );
  cycbm = (CycleButton*)ac1_2->add( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, cincw );

  cycbm->addOption( catalog.getLocale( 634 ) );
  cycbm->addOption( catalog.getLocale( 635 ) );
  cycbm->resize( cycbm->getMaxSize(), cycbm->getHeight() );
  switch( _mode ) {
    case SHOW_CUSTOM_FILES:
      cycbm->setOption( 1 );
      break;
    default:
      cycbm->setOption( 0 );
      break;
  }
  ac1_2->readLimits();

  AContainer *ac1_3 = ac1->add( new AContainer( win, 3, 1 ), 0, 1 );
  ac1_3->setMinSpace( 5 );
  ac1_3->setMaxSpace( 5 );
  ac1_3->setBorderWidth( 0 );
  ac1_3->add( new Text( aguix, 0, 0, catalog.getLocale( 636 ) ), 0, 0, cfix );
  sgcf = (StringGadget*)ac1_3->add( new StringGadget( aguix, 0, 0, 100, _custom_files.c_str(), 0 ),
				    1, 0, cincw );
  flagb = (Button*)ac1_3->add( new Button( aguix,
					   0,
					   0,
					   "F",
					   0 ), 2, 0, cfix );
  
  if ( mode == 0 ) {
    rfcb = (ChooseButton*)ac1->add( new ChooseButton( aguix, 0, 0, ( _request_flags == true ) ? 1 : 0,
						      catalog.getLocale( 294 ), LABEL_RIGHT, 0 ),
				    0, 2, cincwnr );
  }

  AContainer *ac1_5 = ac1->add( new AContainer( win, 2, 1 ), 0, 3 );
  ac1_5->setMinSpace( 5 );
  ac1_5->setMaxSpace( -1 );
  ac1_5->setBorderWidth( 0 );
  okb = (Button*)ac1_5->add( new Button( aguix,
					 0,
					 0,
					 catalog.getLocale( 11 ),
					 0 ), 0, 0, cfix );
  cancelb = (Button*)ac1_5->add( new Button( aguix,
					     0,
					     0,
					     catalog.getLocale( 8 ),
					     0 ), 1, 0, cfix );
  win->contMaximize( true );

  win->setDoTabCycling( true );
  win->show();
  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 == cancelb ) endmode = 1;
          else if ( msg->button.button == flagb ) {
            tstr = OwnOp::getFlag();
            if ( tstr != NULL ) {
              sgcf->insertAtCursor( tstr );
              _freesafe( tstr );
            }
	  }
	  break;
        case AG_KEYPRESSED:
          if ( win->isParent( msg->key.window, false ) == true ) {
            switch ( msg->key.key ) {
              case XK_Return:
                if ( cancelb->getHasFocus() == true ) {
		  endmode = 1;
		} else {
                  endmode=0;
                }
                break;
              case XK_Escape:
                endmode = 1;
                break;
            }
          }
          break;
      }
      aguix->ReplyMessage( msg );
    }
  }
  
  if ( endmode == 0 ) {
    // ok
    if ( mode == 1 ) {
      switch( cycbm->getSelectedOption() ) {
	case 1:
	  _tmode = SHOW_CUSTOM_FILES;
	  break;
	default:
	  _tmode = SHOW_ACTIVE_FILE;
	  break;
      }
      _tcustom_files = sgcf->getText();
    } else {
      switch( cycbm->getSelectedOption() ) {
	case 1:
	  _mode = SHOW_CUSTOM_FILES;
	  break;
	default:
	  _mode = SHOW_ACTIVE_FILE;
	  break;
      }
      if ( rfcb != NULL ) _request_flags = rfcb->getState();
      setCustomFiles( sgcf->getText() );
    }
  }
  delete win;

  return endmode;
}

void InternalViewOp::setRequestFlags( bool nv )
{
  _request_flags = nv;
}

void InternalViewOp::setShowFileMode( show_file_mode_t nv )
{
  _mode = nv;
}

void InternalViewOp::setCustomFiles( std::string nv )
{
  _custom_files = nv;
}

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

void InternalViewOp::setInteractiveRun()
{
    _request_flags = true;
}
