/***************************************************************************
                          FakeFilesListView.cpp  -  description
                             -------------------
    begin                : Sat Dec 1 2001
    copyright            : (C) 2001 by Alex Podolsky
    email                : alexpod@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <iostream.h>
// KDE includes
#include <qdir.h>
#include <qstringlist.h>
#include <qpopupmenu.h>
#include <qclipboard.h>
#include <qapp.h>
#include <qfileinfo.h>
#include <qheader.h>
#include <qdragobject.h>
#include <qcheckbox.h>
#include <qevent.h>
#include <qlist.h>

// KDE includes
#include <kurl.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kopenwith.h>
#include <kio/netaccess.h>
#include <kmessagebox.h>
#include <kmimetype.h>
#include <kcombobox.h>
#include <kconfig.h>
#include <kapplication.h>

// CDBO includes
#include "FakeFilesListView.h"
#include "FakeFilesListView.moc"
#include "FakeFoldersListView.h"
#include "FileItem.h"
#include "FakeFolderItem.h"
#include "FakePropertiesDialog.h"


FakeFilesListView::FakeFilesListView( QWidget *parent, const char *name) : KListView(parent, name){
	
	addColumn(   i18n("Name")  );
    	addColumn(   i18n("Size") );
    	addColumn(  i18n( "Original Location") );
	
    	setColumnAlignment(1, AlignRight);
    	
    	setColumnWidth(0,180);
    	setColumnWidth(1,65);
    	setColumnWidth(2,450);
    	
	setDragEnabled(true);
	setAcceptDrops(true);
	setDropVisualizer(false);
	//setDropVisualizer(true);
	
	setSelectionMode(QListView::Extended);
	//setSelectionModeExt(Konqueror);
	
	fakeFolder = 0;
	ignoreReload = false;
	////////////////////////////////////////////////////////////////////////////////////////
    	/*config = kapp->config();
	config->setGroup("Default Settings");	
	showHidden = config->readBoolEntry("Show Hidden Files On Fake File List", true);///////////////////////////////////////////////////////////////////////////////////////
	*/
	
	popupMenu = new QPopupMenu();
	

	//popupMenu -> insertSeparator();
	
	popupMenu -> insertItem( i18n("File(s) Properties"),   this ,SLOT(filePropertiesSlot()));
	popupMenu -> insertSeparator();
	popupMenu -> insertItem( i18n("Preview File With..."), this ,SLOT(openWithSlot()));	
	popupMenu -> insertItem(UserIcon("cross"), i18n("&Remove Item(s)"), this ,SLOT(remove()));
	
	popupMenu -> insertSeparator();
	popupMenu -> insertItem( BarIcon("reload"), i18n("Reload File List"),   this ,SLOT(reloadListSlot()));
	
	connect( this, SIGNAL(rightButtonPressed(QListViewItem*, const QPoint&, int)),
					 this, SLOT(popupMenuSlot(QListViewItem*, const QPoint&, int)));
					
	connect(  this, SIGNAL(doubleClicked(QListViewItem *)),
						this, SLOT(slotSelectFile(QListViewItem *)));

	connect(	this, SIGNAL(returnPressed(QListViewItem *)),
						this, SLOT(slotSelectFile(QListViewItem *)));
										
	/*connect(  this, SIGNAL(dropped (QDropEvent *, QListViewItem *)),
						this, SLOT(dropOcurred(QDropEvent *, QListViewItem *)));*/
	//setSorting(0,false);
}
FakeFilesListView::~FakeFilesListView(){
}
//---------------------------------------------------------------------------------
void FakeFilesListView::loadFiles( FakeFolderItem *item ){
	//cerr << "load files\n";
	if(ignoreReload)
		return;
	clear();
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//cerr << "load files item->totalEntries() = " << item->totalEntries() << "\n";
	FileEntry *thisEntry;
	BasicFileItem *newItem;
	int ii = 1;
		
	for (thisEntry=item->getFirstFileEntry(); thisEntry; thisEntry=item->getNextFileEntry(), ii++){
		
		//if(showHidden)
		
		newItem = new BasicFileItem(this);
		newItem->setText(0, thisEntry->name);
		
		newItem->setPixmap(0,BarIcon(KMimeType::iconForURL(thisEntry->path), KIcon::SizeSmall ));
		newItem->setText(1, formateSize((long)thisEntry->size));
		newItem->setText(2, " " + thisEntry->path);
		if(thisEntry->immutable)
			newItem->setText(2, i18n(" Imported from previous session"));
		newItem->i = thisEntry;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	BasicFolderItem *folderItem;
	for (FakeFolderItem *i = (FakeFolderItem *)item->firstChild(); ; i=(FakeFolderItem *)i->nextSibling()){
		if(!i)
			break;
		folderItem = new BasicFolderItem(this);
		folderItem->setText(0, i->getName());
		//cerr << "may be nxt time\n";
		folderItem->setPixmap(0,i->getSmallIcon());
		folderItem->setText(1, formateSize(i->getSize()));
		folderItem->setText(2, "");
		folderItem->i = i;
	}
	
	fakeFolder = item;
	//cerr << "oooouuut load files\n";
}
//---------------------------------------------------------------------------------
void FakeFilesListView::reloadListSlot(){
	loadFiles(fakeFolder);
}
//---------------------------------------------------------------------------------
void FakeFilesListView::slotSelectFile(QListViewItem * item){
	BasicFolderItem *folderItem = dynamic_cast<BasicFolderItem *>(item);
	if(!folderItem)
		return;
	else{
		fakeFolder->setOpen(true);
		((FakeFoldersListView *)fakeFolder->listView())->slotSelectFile(folderItem->i);
		//fakeFolder->listView()->ensureItemVisible(folderItem->i);
	}
}
//===========================================================
QString FakeFilesListView::formateSize(unsigned long size) {
	QString buff;
	if(size < 1024)
		return QString::number(size) + "B";
	else if(size / 1024 < 1024){
		//return QString::number(size / 1024) + "KB";
		buff = buff.setNum( ((double)size) / 1024, 'f', 1) + "KB";
		return buff;
	}
	else if(size / 1024  / 1024 < 1024){
		buff = buff.setNum( ((double)size) / 1024 / 1024, 'f', 1) + "MB";
		return buff;
	}
	else{
		buff = buff.setNum( ((double)size) / 1024 / 1024  / 1024, 'f', 1) + "GB";
		return buff;
	}
	return "";
}
//---------------------------------------------------------------------------------
void FakeFilesListView::popupMenuSlot(QListViewItem* item, const QPoint& point, int){
	if ( !item ){
		if(!fakeFolder)
			return;
		else{
			((FakeFoldersListView *)fakeFolder->listView())->setMultiple(false);
			((FakeFoldersListView *)fakeFolder->listView())->slotMenu(fakeFolder, point, 0);
			return;
		}
	}
	else{
		setSelected(item, true);
		BasicFolderItem *folderItem = dynamic_cast<BasicFolderItem *>(item);
  		if(!folderItem){
  			if(item->text(2) == i18n(" Imported from previous session")){
  				((FakeFoldersListView *)fakeFolder->listView())->setMultiple(true);
				((FakeFoldersListView *)fakeFolder->listView())->setFakeListView(this);
  				((FakeFoldersListView *)fakeFolder->listView())->slotMenu(fakeFolder, point, 0);
  			}
  			else
				popupMenu->popup(point);
		}
		else{
			((FakeFoldersListView *)fakeFolder->listView())->setMultiple(true);
			((FakeFoldersListView *)fakeFolder->listView())->setFakeListView(this);
			((FakeFoldersListView *)fakeFolder->listView())->slotMenu(folderItem->i, point, 0);
		}
	}
}
//---------------------------------------------------------------------------------
void FakeFilesListView::filePropertiesSlot(){
	
	QList<QListViewItem> list = selectedItems();
	FakePropertiesDialog *propDlg;
	//cerr << "number of selected = " << list.count() << endl;
	if(list.count() == 0)
		return;
	else if(list.count() == 1){
		QListViewItem *fItem = currentItem();
		BasicFolderItem *folderItem = dynamic_cast<BasicFolderItem *>(fItem);
  	
		if(!folderItem){
			propDlg = new FakePropertiesDialog(fakeFolder, ((BasicFileItem *)fItem)->i, this, "propDlg" );
				//fakeFolder->getEntry(fItem->text(0).stripWhiteSpace()), this, "propDlg" );
		}
		else{
			propDlg = new FakePropertiesDialog(folderItem->i, this, "propDlg" );
		}
	}
	else{
		selectedFoldersList.clear();
		selectedEntriesList.clear();
								
		BasicFolderItem *folderItem;
		for(QListViewItem *item = list.first(); item; item = list.next()){
			folderItem = dynamic_cast<BasicFolderItem *>(item);
			if(!folderItem)		
				selectedEntriesList.append(((BasicFileItem *)item)->i);
				//selectedEntriesList.append(fakeFolder->getEntry(item->text(0).stripWhiteSpace()));
			else
				selectedFoldersList.append(folderItem->i);
		}
		propDlg = new FakePropertiesDialog(fakeFolder, &selectedFoldersList, &selectedEntriesList, this, "propDlg" );
	}
  	//connect( propDlg, SIGNAL( applied() ), this , SLOT( currentModifiedSlot() ) );
}
//=============================================
void FakeFilesListView:: currentModifiedSlot(){
	emit modified();
	reloadListSlot();
}
//---------------------------------------------------------------------------------
void FakeFilesListView::openWithSlot(){
	QListViewItem *fItem = currentItem();
  	if (!fItem) return;
  	
	QString sp = fItem->text(2).stripWhiteSpace();
	
	QStringList list;
	list.append(sp);
	
	KFileOpenWithHandler *kfowh = new KFileOpenWithHandler();
	
	kfowh -> displayOpenWithDialog( KURL::List( list ) );
}
//---------------------------------------------------------------------------------
void FakeFilesListView::remove(){
	ignoreReload = true;
	QList<QListViewItem> list = selectedItems();
	bool loopCanceled = false;
	//cerr << "number of selected = " << list.count() << endl;
	
	BasicFolderItem *folderItem;
	for(QListViewItem *item = list.first(); item; item = list.next()){
		folderItem = dynamic_cast<BasicFolderItem *>(item);
		if(!folderItem){		
			if(!fakeFolder->removeEntry(((BasicFileItem *)item)->i)){
				int result = KMessageBox::warningYesNo(this,
					i18n("You cannot remove this item. "\
					"It was imported from the previous session"),
        				i18n("Cannot Remove ") + ((BasicFileItem *)item)->i->name,
        				QString(i18n("Skip")),
        				QString(i18n("Cancel")));
        			switch(result){
					case KMessageBox::Yes:
       					break;
       				case KMessageBox::No:
       					loopCanceled = true;
       					break;
				}			
			}
		}
		else{
			if(folderItem->i->isImmutable()){
				int result = KMessageBox::warningYesNo(this,
					i18n("You cannot remove this folder. "\
					"It was imported from the previous session"),
        				i18n("Cannot remove ") + folderItem->i->getName(),
        				QString(("Skip")),
        				QString(i18n("Cancel")));
        			switch(result){
					case KMessageBox::Yes:
       					break;
       				case KMessageBox::No:
       					loopCanceled = true;
       					break;
				}
			}
			else{
				fakeFolder->subtractFromSize((folderItem->i)->getSize());
				delete folderItem->i;
			}
		}
		if(loopCanceled)
			break;
	}
	ignoreReload = false;
	reloadListSlot();
	emit modified();
	((FakeFoldersListView *)fakeFolder->listView())->resetSize();
}
//---------------------------------------------------------------------------------------------
void FakeFilesListView::keyPressEvent(QKeyEvent *e){
	if(e->key() == Key_Delete){
		remove();
	}
	if(e->key() == Key_F5){
		reloadListSlot();
	}
	KListView::keyPressEvent(e);
}
//===================================================
//=======DND============
//===================================================
//===================================================



//===================================
bool FakeFilesListView::acceptDrag (QDropEvent* event) const{
	if(QTextDrag::canDecode(event)){
		if(!fakeFolder)
			return true;
		QListViewItem *selected = itemAt(event->pos());
		
		if(lastSelected == selected && selected == selectedItem())
			return true;
			
		((FakeFoldersListView *)fakeFolder->listView())->setPointForDrop(mapToGlobal(event->pos()));
		
		if(selected){
		//cerr << "itemAt() = " << iiii->text(0) << "\n";
			selected->listView()->clearSelection();
			((FakeFilesListView *)selected->listView())->lastSelected = selected;
			BasicFolderItem *item = dynamic_cast<BasicFolderItem *>(selected);
			if(!item){
				fakeFolder->listView()->ensureItemVisible(fakeFolder);
				((FakeFoldersListView *)fakeFolder->listView())->setParentForDrop(fakeFolder);
				if(event->source() == (FakeFilesListView *)this){
					return false;
				}
			}
			else{
				selected->listView()->setSelected(selected, true);
				((FakeFoldersListView *)fakeFolder->listView())->setParentForDrop(item->i);
				fakeFolder->listView()->ensureItemVisible(item->i);
			}
			
		}
		else{
			selected = firstChild();
			if(selected){
				selected->listView()->clearSelection();
				if(event->source() == (FakeFilesListView *)this){
					return false;
				}
				fakeFolder->listView()->ensureItemVisible(fakeFolder);
				((FakeFoldersListView *)fakeFolder->listView())->setParentForDrop(fakeFolder);
			}
		}
		return true;
	}
	else
		return false;
}
//=============================================
QDragObject *FakeFilesListView::dragObject(){
	QListViewItem *item = currentItem();
	if ( !item || item->text(2) == i18n(" Imported from previous session"))
		return 0;
	
	
	BasicFolderItem *folderItem = dynamic_cast<BasicFolderItem *>(item);
  	if(folderItem && folderItem->i->isImmutable())
  		return 0;
	((FakeFilesListView *)item->listView())->selectedList.clear();
  	((FakeFilesListView *)item->listView())->selectedList = selectedItems();
	
	QDragObject *d = new QTextDrag("This package came from your friendly FakeFilesListView", (QWidget *)this);
	const QPixmap *p = currentItem()->pixmap(0);
	d->setPixmap(*p);
	return d;
}
//=============================================
void FakeFilesListView::copySelectedTo(FakeFolderItem *targetFolder){
	bool bbbb = false;//temprorary bug fix///////////////////////////////////////////////////////////////////////
	if(fakeFolder == targetFolder){
		/*KMessageBox::sorry(this,
              	"You can't drop a directory onto itself");
		return;*/
		bbbb = true;
	}
	//QString name;
	bool cancel;
	ignoreReload = true;
	
	//FileEntry *thisEntry;
		
	((FakeFoldersListView *)fakeFolder->listView())->setDragedItem(0);
	//cerr << "number of selected = " << selectedList.count() << endl;
	for(QListViewItem *item = selectedList.first(); item; item = selectedList.next()){
		if(!dynamic_cast<BasicFolderItem *>(item)){
			if(bbbb)
				continue;
			//name = item->text(0).stripWhiteSpace();
			//((BasicFileItem *)item)->i->size;
			if(!((FakeFoldersListView *)fakeFolder->listView())->checkChildNameClash(((BasicFileItem *)item)->i->name, &cancel)){
				if(cancel)
					return;
				else
					continue;
			}
			//thisEntry = fakeFolder->getEntry(name);
			if(!((FakeFoldersListView *)fakeFolder->listView())->canFit(((BasicFileItem *)item)->i->size / 1024 / 1024,
					((BasicFileItem *)item)->i->name)){
       			((FakeFoldersListView *)fakeFolder->listView())->resetSize();
       			return;
       		}
			targetFolder->addEntry(((BasicFileItem *)item)->i);
		}
		else{
			((FakeFoldersListView *)fakeFolder->listView())->setDragedItem(((BasicFolderItem *)item)->i);
			
			if(!((FakeFoldersListView *)fakeFolder->listView())->copyItemsSlot()){
				ignoreReload = false;
				return;
			}
		}
	}
	ignoreReload = false;
	///reloadListSlot();
	//((FakeFoldersListView *)fakeFolder->listView())->setParentForDrop(fakeFolder);
	
	emit modified();
	
	///////////////////////////////////////////////////////////////
}
//=============================================
void FakeFilesListView::moveSelectedTo(FakeFolderItem *targetFolder){
	if(fakeFolder == targetFolder){
		KMessageBox::sorry(this,
              	i18n("Cannot move to the same directory."));
		return;
	}
	bool cancel;
	for(QListViewItem *item = selectedList.first(); item; item = selectedList.next()){
		if(!dynamic_cast<BasicFolderItem *>(item)){
			if(!((FakeFoldersListView *)fakeFolder->listView())->checkChildNameClash(((BasicFileItem *)item)->i->name, &cancel)){
				if(cancel)
					return;
				else
					continue;
			}
			targetFolder->addEntry(((BasicFileItem *)item)->i);
			fakeFolder->removeEntry(((BasicFileItem *)item)->i);
		}
		else{
			((FakeFoldersListView *)fakeFolder->listView())->setDragedItem(((BasicFolderItem *)item)->i);
			if(!((FakeFoldersListView *)fakeFolder->listView())->moveItemsSlot()){
				//ignoreReload = false;
				return;
			}
		}
	}
	//ignoreReload = false;
	reloadListSlot();
	emit modified();
	//((FakeFoldersListView *)fakeFolder->listView())->setParentForDrop(fakeFolder);
}
//===================================================
//===================================================
//===================================================
//===================================================
//---------------------------------------------------------------------------------
/*void FakeFilesListView::checkShowHidden(){
	if(cnt){
		showHidden = cnt->getShowHiddenChk()->isChecked();
		loadDir(dirPath);
		////////////////////////////////////////////////////////////////////////////////////////
		config->setGroup("Default Settings");	
		config->writeEntry("Show Hidden Files On Fake File List", showHidden);
	}
}*/
//===================================================
//===================================================
//===================================================
//===================================================
BasicFolderItem::BasicFolderItem(QListView * parent): QListViewItem(parent){
	//
}
//===================================================
QString BasicFolderItem::key ( int column, bool ) const{
	if(column == 1){
		QString tmpString;
		tmpString.sprintf( "%08d", (int)i->getSize() );
		return tmpString;
	}
	return  QString(".1") + text(column);
}
//===================================================
BasicFileItem::BasicFileItem(QListView * parent): QListViewItem(parent){
	//setHeight(30);
}
//===================================================
QString BasicFileItem::key ( int column, bool ) const{
	if(column == 1){
		QString tmpString;
		tmpString.sprintf( "%08d", i->size );
		return tmpString;
	}
	return text(column);
}
