/* wconfig_listview.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2006-2020 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 "wconfig_listview.hh"
#include "wconfig.h"
#include "worker.h"
#include "aguix/acontainerbb.h"
#include "aguix/fieldlistview.h"
#include "aguix/button.h"
#include "worker_locale.h"

ListViewPanel::ListViewPanel( AWindow &basewin, WConfig &baseconfig ) : WConfigPanel( basewin, baseconfig )
{
}

ListViewPanel::~ListViewPanel()
{
}

int ListViewPanel::create()
{
  Panel::create();

  unsigned int j, ui;
  int trow;
  const int cincw = AContainer::ACONT_MINH +
                    AContainer::ACONT_MINW +
                    AContainer::ACONT_MAXH;
  const int cincwnr = cincw +
                      AContainer::ACONT_NORESIZE;
  const int cmin = AContainer::ACONT_MINH +
                   AContainer::ACONT_MINW;

  AContainer *ac0 = setContainer( new AContainer( this, 1, 3 ), true );
  ac0->setMinSpace( 5 );
  ac0->setMaxSpace( 5 );
  ac0->setBorderWidth( 5 );

  addMultiLineText( catalog.getLocale( 676 ),
                    *ac0,
                    0, 0,
                    NULL, NULL );

  for ( int side = 0; side < 2; side++ ) {
    AContainer *ac1 = ac0->add( new AContainerBB( this, 1, 2 ), 0, side + 1 );
    ac1->setMinSpace( 5 );
    ac1->setMaxSpace( 5 );
    ac1->setBorderWidth( 10 );

    ac1->add( new Text( _aguix, 0, 0,
                        ( side == 0 ) ? catalog.getLocale( 19 ) : catalog.getLocale( 20 )
                        ),
              0, 0, cincwnr );

    AContainer *ac1_1 = ac1->add( new AContainer( this, 3, 1 ), 0, 1 );
    ac1_1->setMinSpace( 5 );
    ac1_1->setMaxSpace( 5 );
    ac1_1->setBorderWidth( 0 );
    AContainer *ac1_1_1 = ac1_1->add( new AContainer( this, 1, 3 ), 0, 0 );
    ac1_1_1->setMinSpace( 0 );
    ac1_1_1->setMaxSpace( 0 );
    ac1_1_1->setBorderWidth( 0 );

    ac1_1_1->add( new Text( _aguix, 0, 0, catalog.getLocale( 238 ) ), 0, 0, cincwnr );
    lv1[side] = (FieldListView*)ac1_1_1->add( new FieldListView( _aguix,
                                                                 0, 0,
                                                                 100, 50,
                                                                 0 ), 0, 1, cmin );
    lv1[side]->connect( this );
    AContainer *ac1_1_1_1 = ac1_1_1->add( new AContainer( this, 2, 1 ), 0, 2 );
    ac1_1_1_1->setMinSpace( 0 );
    ac1_1_1_1->setMaxSpace( 0 );
    ac1_1_1_1->setBorderWidth( 0 );
    upb[side] = (Button*)ac1_1_1_1->add( new Button( _aguix,
                                                     0, 0,
                                                     catalog.getLocale( 236 ),
                                                     0 ), 0, 0, cincw );
    upb[side]->connect( this );
    downb[side] = (Button*)ac1_1_1_1->add( new Button( _aguix,
                                                       0, 0,
                                                       catalog.getLocale( 237 ),
                                                       0 ), 1, 0, cincw );
    downb[side]->connect( this );
    lv1[side]->setHBarState(2);
    lv1[side]->setVBarState(2);
    lv1[side]->setAcceptFocus( true );
    lv1[side]->setDisplayFocus( true );
    
    AContainer *ac1_1_2 = ac1_1->add( new AContainer( this, 1, 4 ), 1, 0 );
    ac1_1_2->setMinSpace( 5 );
    ac1_1_2->setMaxSpace( -1 );
    ac1_1_2->setBorderWidth( 5 );
    delb[side] = (Button*)ac1_1_2->add( new Button( _aguix,
                                                    0, 0,
                                                    catalog.getLocale(239),
                                                    0 ), 0, 1, cincw );
    delb[side]->connect( this );
    insb[side] = (Button*)ac1_1_2->add( new Button( _aguix,
                                                    0, 0,
                                                    catalog.getLocale(240),
                                                    0 ), 0, 2, cincw );
    insb[side]->connect( this );

    AContainer *ac1_1_3 = ac1_1->add( new AContainer( this, 1, 2 ), 2, 0 );
    ac1_1_3->setMinSpace( 0 );
    ac1_1_3->setMaxSpace( 0 );
    ac1_1_3->setBorderWidth( 0 );

    ac1_1_3->add( new Text( _aguix, 0, 0, catalog.getLocale( 677 ) ), 0, 0, cincwnr );
    lv2[side] = (FieldListView*)ac1_1_3->add(new FieldListView( _aguix,
                                                                0, 0,
                                                                lv1[side]->getWidth(),
                                                                50,
                                                                0 ), 0, 1, cmin );
    lv2[side]->connect( this );
    lv2[side]->setHBarState(2);
    lv2[side]->setVBarState(2);
    lv2[side]->setAcceptFocus( true );
    lv2[side]->setDisplayFocus( true );
    
    bool *sels = new bool[WorkerTypes::getAvailListColsSize()];
    for ( j = 0; j < WorkerTypes::getAvailListColsSize(); j++ ) {
      sels[j] = false;
    }
    for ( ui = 0; ui < _baseconfig.getVisCols( side )->size(); ui++ ) {
      for ( j = 0; j < WorkerTypes::getAvailListColsSize(); j++ ) {
        if ( WorkerTypes::availListCols[j].type == (*_baseconfig.getVisCols( side ))[ui] ) break;
      }
      if ( j < WorkerTypes::getAvailListColsSize() ) {
        trow = lv1[side]->addRow();
        lv1[side]->setText( trow, 0, catalog.getLocale( WorkerTypes::availListCols[j].catalogid ) );
        lv1[side]->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
        sels[j]=true;
      }
    }
    for ( j = 0; j < WorkerTypes::getAvailListColsSize(); j++ ) {
      if ( sels[j] == false ) {
        trow = lv2[side]->addRow();
        lv2[side]->setText( trow, 0, catalog.getLocale( WorkerTypes::availListCols[j].catalogid ) );
        lv2[side]->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
      }
    }
    delete [] sels;

    lv1[side]->maximizeX();
    lv2[side]->maximizeX();
    if ( lv1[side]->getWidth() < 100 )
      lv1[side]->resize( 100, lv1[side]->getHeight() );
    lv1[side]->resize( lv1[side]->getWidth(), 8 * lv1[side]->getRowHeight() );

    if ( lv2[side]->getWidth() < 100 )
      lv2[side]->resize( 100, lv2[side]->getHeight() );
    lv2[side]->resize( lv2[side]->getWidth(), 8 * lv2[side]->getRowHeight() );

    ac1_1_1->readLimits();
    ac1_1->readLimits();
  }
  contMaximize( true );
  return 0;
}
  
int ListViewPanel::saveValues()
{
  int trow2;
  std::vector<WorkerTypes::listcol_t> nvc;
  unsigned int j;

  for ( int side = 0; side < 2; side++ ) {
    nvc.clear();
    
    trow2 = 0;
    while ( lv1[side]->isValidRow( trow2 ) == true ) {
      for ( j = 0; j < WorkerTypes::getAvailListColsSize(); j++ ) {
        if ( strcmp( catalog.getLocale( WorkerTypes::availListCols[j].catalogid ),
                     lv1[side]->getText( trow2, 0 ).c_str() ) == 0 ) {
          nvc.push_back( WorkerTypes::availListCols[j].type );
        }
      }
      trow2++;
    }

    _baseconfig.clearVisCols( side );
    _baseconfig.setVisCols( side, &nvc );
  }
  return 0;
}

void ListViewPanel::run( Widget *elem, const AGMessage &msg )
{
  int side;
  int trow;
  unsigned int j;
  int i1, i2;

  if ( msg.type == AG_BUTTONCLICKED ) {
    if ( msg.button.button == upb[1] ||
         msg.button.button == downb[1] ||
         msg.button.button == insb[1] ||
         msg.button.button == delb[1] )
      side = 1;
    else
      side = 0;

    if ( msg.button.button == upb[side] ) {
      trow = lv1[side]->getActiveRow();
      if ( lv1[side]->isValidRow( trow ) == true ) {
        if ( trow > 0) {
          lv1[side]->swapRows( trow, trow - 1 );
          lv1[side]->redraw();
          lv1[side]->showActive();
        }
      }
    } else if ( msg.button.button == downb[side] ) {
      trow = lv1[side]->getActiveRow();
      if ( lv1[side]->isValidRow( trow ) == true ) {
        if ( trow < ( lv1[side]->getElements() - 1 ) ) {
          lv1[side]->swapRows( trow, trow + 1 );
          lv1[side]->redraw();
          lv1[side]->showActive();
        }
      }
    } else if ( msg.button.button == delb[side] ) {
      int trow2, trow3;
      trow = lv1[side]->getActiveRow();
      if ( lv1[side]->isValidRow( trow ) == true ) {
        // first find entry from availlist
        for ( j = 0, i1 = -1; j < WorkerTypes::getAvailListColsSize(); j++ ) {
          if ( strcmp( catalog.getLocale( WorkerTypes::availListCols[j].catalogid ),
                       lv1[side]->getText( trow, 0 ).c_str() ) == 0 ) {
            i1 = (int)j;
          }
        }
        // now find insertion position in second LV
        trow2 = 0;
        i2=0;
        int i3;
        while ( lv2[side]->isValidRow( trow2 ) == true ) {
          // for each entry search pos in availlist
          i3 = -1;
          for ( j = 0; j < WorkerTypes::getAvailListColsSize(); j++ ) {
            if ( strcmp( catalog.getLocale( WorkerTypes::availListCols[j].catalogid ),
                         lv2[side]->getText( trow2, 0 ).c_str() ) == 0 ) i3 = (int)j;
          }
          // for each entry with lower position raise the insertion position
          if(i3<i1) i2++;
          trow2++;
        }
        trow3 = lv2[side]->insertRow( i2 );
        lv2[side]->setText( trow3, 0, lv1[side]->getText( trow, 0 ) );
        lv2[side]->setPreColors( trow3, FieldListView::PRECOLOR_ONLYACTIVE );
        lv1[side]->deleteRow( trow );
        lv1[side]->redraw();
        lv2[side]->redraw();
      }
    } else if ( msg.button.button == insb[side] ) {
      int trow2;
      trow = lv2[side]->getActiveRow();
      if ( lv2[side]->isValidRow( trow ) == true ) {
        trow2 = lv1[side]->addRow();
        lv1[side]->setText( trow2, 0, lv2[side]->getText( trow, 0 ) );
        lv1[side]->setPreColors( trow2, FieldListView::PRECOLOR_ONLYACTIVE );
        lv2[side]->deleteRow( trow );
        lv1[side]->redraw();
        lv2[side]->redraw();
      }
    }
  }
}
