/* fieldlistviewdnd.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2002-2026 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 "fieldlistviewdnd.h"
#include "awindow.h"
#include "guielement.h"

const char *FieldListViewDND::type="FieldListViewDND";

FieldListViewDND::~FieldListViewDND()
{
  removealldndtexts();
}

FieldListViewDND::FieldListViewDND( AGUIX *taguix,
				    int tx,
				    int ty,
				    int width,
				    int height,
				    int tdata ) : FieldListView( taguix,
								 tx,
								 ty,
								 width,
								 height,
								 tdata )
{
  dndMode = DND_IDLE;
  dndtext = NULL;
}

void FieldListViewDND::handleSelect(Message *msg)
{
    int win_x, win_y;
  
    if ( isCreated() == false ) return;

    if ( dndMode != DND_IDLE ) {
        handleDND( msg );
        return;
    }
    if ( msg->type == ButtonPress ) {
        if ( msg->window != win ) return;
        if ( selectMode != SELECT_IDLE ) {
            if ( ( msg->button == _scroll_button ) &&
                 ( selectMode == SELECT_HOLD ) ){
                dndMode = DND_ACTIVE;
        
                _aguix->queryPointer( win, &win_x, &win_y );
                if ( isValidRow( clickLastSelectedRow ) == true ) {
                    colorclass_t ti;
	  
                    if ( clickLastSelectedRow == activerow ) {
                        if ( getSelect( clickLastSelectedRow ) == true )
                            ti = CC_SELACT;
                        else
                            ti = CC_ACTIVE;
                    } else {
                        if ( getSelect( clickLastSelectedRow ) == true )
                            ti = CC_SELECT;
                        else
                            ti = CC_NORMAL;
                    }

                    std::string tstr;
                    if ( clickLastSelectedRow >= 0 && clickLastSelectedRow < (int)dndtexts.size() ) {
                        tstr = dndtexts[clickLastSelectedRow];
                    } else {
                        tstr = elementarray[ clickLastSelectedRow ]->getText( 0 );
                    }

                    FieldLVRowData *dp = getDataExt( clickLastSelectedRow );

                    m_dnd_start_data = dnd_data();

                    m_dnd_start_data.row = clickLastSelectedRow;
                    if ( dp != NULL ) {
                        m_dnd_start_data.element = dp->duplicate();
                    } else {
                        m_dnd_start_data.element = NULL;
                    }

                    dndtext = new DNDText( _aguix,
                                           tstr.c_str(),
                                           getFG( clickLastSelectedRow, ti ),
                                           getBG( clickLastSelectedRow, ti),
                                           font );
                    dndtext->create();

                    _aguix->startXDND( this, win, _select_button, _scroll_button );
                }
            }
            return;
        }
    }
    FieldListView::handleSelect( msg );
}

void FieldListViewDND::handleDND( Message *msg )
{
    if ( isCreated() == false || dndtext == NULL ) return;

    if ( ( msg->type == MotionNotify ) ||
         ( msg->type == Expose ) ) {
        dndtext->handler( msg );
    }
}

const char *FieldListViewDND::getType() const
{
  return type;
}

bool FieldListViewDND::isType(const char *qtype) const
{
  if(strcmp(type,qtype)==0) return true;
  return false;
}

void FieldListViewDND::removealldndtexts()
{
    dndtexts.clear();
}

void FieldListViewDND::replacedndtext( int index2, const char *tstr )
{
    if ( index2 < 0 || index2 >= (int)dndtexts.size() ) return;
    dndtexts[index2] = tstr;
}

void FieldListViewDND::adddndtext( const char *tstr )
{
    dndtexts.push_back( tstr );
}

void FieldListViewDND::setSizeDNDText(int ns)
{
    int elems = (int)dndtexts.size();
    while ( elems < ns ) {
        dndtexts.push_back( "" );
        elems++;
    }
    while ( elems > ns ) {
        dndtexts.pop_back();
        elems--;
    }
}

void FieldListViewDND::cleanupDNDStart()
{
    delete dndtext;
    dndtext = NULL;

    if ( dndMode != DND_IDLE ) {
        switch ( selectMode ) {
            case SELECT_SCROLL_UP:
            case SELECT_SCROLL_DOWN:
                _aguix->disableTimer();
            case SELECT_HOLD: {
                setSelect( clickLastSelectedRow, false );
                runSelectHandler( clickLastSelectedRow );
                AGMessage *agmsg = AGUIX_allocAGMessage();
                agmsg->fieldlv.lv = this;
                agmsg->fieldlv.row = clickFirstSelectedRow;
                agmsg->fieldlv.time = time( NULL );
                agmsg->fieldlv.mouse = true;
                if ( clickSelected == 1 ) {
                    agmsg->type = AG_FIELDLV_ONESELECT;
                } else {
                    agmsg->type = AG_FIELDLV_MULTISELECT;
                }
                msgAndCB( std::unique_ptr<AGMessage>( agmsg ) );
                break;
            }
            default:
                break;
        }
        _aguix->msgUnlock( this );
        selectMode = SELECT_IDLE;
        dndMode = DND_IDLE;
    }
}

void FieldListViewDND::processDNDDrop( AGMessage *agmsg )
{
    if ( ! agmsg ) return;

    agmsg->dnd.target_element = this;

    msgAndCB( std::unique_ptr<AGMessage>( agmsg ) );
}

void FieldListViewDND::cancelDND()
{
    delete dndtext;
    dndtext = NULL;
    dndMode = DND_DEACTIVE;
}

void FieldListViewDND::addDragData( AGMessage *agmsg )
{
    agmsg->dnd.source_element = this;
    agmsg->dnd.specialinfo.value = m_dnd_start_data.row;
    agmsg->dnd.specialinfo.rowDataP = m_dnd_start_data.element;
    m_dnd_start_data.element = nullptr;
}

int FieldListViewDND::fillDropData( std::string *res )
{
    if ( ! res ) return 1;

    if ( m_dnd_start_data.element && m_dnd_data_callback ) {
        std::string data = m_dnd_data_callback( this, m_dnd_start_data.element );

        if ( ! data.empty() ) {
            *res = "file://";
            *res += data;
            *res += "\r\n";

            return 0;
        }
    }

    return 2;
}

void FieldListViewDND::setDNDDataCallback( std::function< std::string( FieldListViewDND *lv, const FieldLVRowData *rowdata ) > cb )
{
    m_dnd_data_callback = cb;
}
