/***************************************************************************
 *   Copyright (C) 2005 by Niklas Knutsson                                 *
 *   nq@altern.org                                                         *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "qalculatedatasetsdialog.h"

#include "qalculateeditdatasetdialog.h"
#include "qalculateeditdataobjectdialog.h"
#include "qalculate_tde_utils.h"
#include "qalculatebuttonwithdata.h"
#include <kpushbutton.h>
#include <tqsplitter.h>
#include <tqvbox.h>
#include <tqhbox.h>
#include <tqgrid.h>
#include <tdelistview.h>
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <tqlayout.h>
#include <tqgroupbox.h>
#include <tqscrollview.h>
#include <ktextbrowser.h>
#include <tqlabel.h>
#include <kactivelabel.h>
#include <kiconloader.h>
#include <klineedit.h>

extern PrintOptions printops;
extern TQWidget *expressionWidget;

QalculateDataSetsDialog::QalculateDataSetsDialog(TQWidget *parent, const char *name) : KDialogBase(parent, name, false, i18n("Data Sets"), Close, Close, false) {

	dataset_edit_dialog = NULL;
	object_edit_dialog = NULL;

	TQVBox *box = makeVBoxMainWidget();
	TQSplitter *splitter = new TQSplitter(TQt::Vertical, box);

	TQVBox *group1 = new TQVBox(splitter);
	TQVBox *group2 = new TQVBox(splitter);

	splitter = new TQSplitter(TQt::Horizontal, group1);
	TQWidget *widget = new TQWidget(splitter);
	widget->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Expanding);
	TQVBoxLayout *vbox = new TQVBoxLayout(widget, spacingHint(), spacingHint());
	vbox->addWidget(new TQLabel(i18n("Data Sets:"), widget));
	dataSetsView = new TDEListView(widget);	
	vbox->addWidget(dataSetsView);
	dataSetsView->addColumn(i18n("Data Set"));
	dataSetsView->setRootIsDecorated(false);
	TQHBoxLayout *hbox = new TQHBoxLayout(vbox);
	hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
	newDataSetButton = new TQPushButton(i18n("New"), widget);
	hbox->addWidget(newDataSetButton);
	editDataSetButton = new TQPushButton(i18n("Edit"), widget);
	hbox->addWidget(editDataSetButton);
	deleteDataSetButton = new TQPushButton(i18n("Delete"), widget);
	hbox->addWidget(deleteDataSetButton);
	TQVBox *vbox2 = new TQVBox(splitter);
	vbox2->setMargin(spacingHint());
	vbox2->setSpacing(spacingHint());
	new TQLabel(i18n("Description:"), vbox2);
	descriptionBrowser = new KTextBrowser(vbox2);

	splitter = new TQSplitter(TQt::Horizontal, group2);
	widget = new TQWidget(splitter);
	widget->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Expanding);
	vbox = new TQVBoxLayout(widget, spacingHint(), spacingHint());
	vbox->addWidget(new TQLabel(i18n("Objects:"), widget));
	objectsView = new TDEListView(widget);
	vbox->addWidget(objectsView);
	objectsView->addColumn(i18n("Object"));
	objectsView->setRootIsDecorated(false);
	hbox = new TQHBoxLayout(vbox);
	hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
	newObjectButton = new TQPushButton(i18n("New"), widget);
	hbox->addWidget(newObjectButton);
	editObjectButton = new TQPushButton(i18n("Edit"), widget);
	hbox->addWidget(editObjectButton);
	deleteObjectButton = new TQPushButton(i18n("Delete"), widget);
	hbox->addWidget(deleteObjectButton);
	vbox2 = new TQVBox(splitter);
	vbox2->setMargin(spacingHint());
	vbox2->setSpacing(spacingHint());
	new TQLabel(i18n("Attributes:"), vbox2);
	attributesView = new TQScrollView(vbox2);
	attributesView->setResizePolicy(TQScrollView::AutoOneFit);
	attributesView->setFrameStyle(TQFrame::NoFrame);
	attributesGrid = new TQGrid(3, TQt::Horizontal, attributesView->viewport());
	attributesGrid->setSpacing(spacingHint());
	attributesView->addChild(attributesGrid);

	resize(TQSize(675, 525).expandedTo(size()));

	connect(newDataSetButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(newDataSet()));
	connect(editDataSetButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(editDataSet()));
	connect(deleteDataSetButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(deleteDataSet()));
	connect(dataSetsView, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(dataSetSelected()));
	connect(dataSetsView, TQ_SIGNAL(doubleClicked(TQListViewItem*)), this, TQ_SLOT(dataSetDoubleClicked(TQListViewItem*)));

	connect(newObjectButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(newObject()));
	connect(editObjectButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(editObject()));
	connect(deleteObjectButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(deleteObject()));
	connect(objectsView, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(objectSelected()));
	connect(objectsView, TQ_SIGNAL(doubleClicked(TQListViewItem*)), this, TQ_SLOT(objectDoubleClicked(TQListViewItem*)));

}

QalculateDataSetsDialog::~QalculateDataSetsDialog() {}

void QalculateDataSetsDialog::updateDataSetTree() {

	dataSetItems.clear();
	objectItems.clear();
	dataSetsView->clear();
	DataSet *ds;
	TQListViewItem *i;
	bool b = false;
	dataSetsView->blockSignals(true);
	for(size_t index = 1; ; index++) {
		ds = CALCULATOR->getDataSet(index);
		if(!ds) break;
		i = new TDEListViewItem(dataSetsView, ds->title().c_str());
		dataSetItems[i] = ds;
		if(ds == selected_dataset) {
			dataSetsView->blockSignals(false);
			dataSetsView->setSelected(i, true);
			dataSetsView->blockSignals(true);
			b = true;
		}
	}
	dataSetsView->blockSignals(false);
	if(!b) {
		dataSetsView->selectAll(false);
		selected_dataset = NULL;
	}

}

#define UPDATE_SELECTED_DATASET		TQListViewItem *i3 = dataSetsView->selectedItem(); if(!i3) return; selected_dataset = dataSetItems[i3]; if(!selected_dataset) return;
#define UPDATE_SELECTED_OBJECT		TQListViewItem *i2 = objectsView->selectedItem(); if(!i2) return; selected_object = objectItems[i2]; if(!selected_object) return;
#define CHECK_IF_DATASET_STILL_THERE			if(!CALCULATOR->stillHasFunction(selected_dataset)) {KMessageBox::error(this, i18n("Data set does not exist anymore.")); emit dataSetsChanged(); return;}

void QalculateDataSetsDialog::deleteDataSet() {
	UPDATE_SELECTED_DATASET
	CHECK_IF_DATASET_STILL_THERE
	if(selected_dataset->isLocal()) {
		selected_object = NULL;
		//ensure that all references are removed in Calculator
		selected_dataset->destroy();
		//update menus and trees
		emit dataSetsChanged();
	}
}


void QalculateDataSetsDialog::editDataSet() {
	UPDATE_SELECTED_DATASET
	CHECK_IF_DATASET_STILL_THERE
	if(!dataset_edit_dialog) {
		dataset_edit_dialog = new QalculateEditDataSetDialog(this);
	}
	DataSet *ds = dataset_edit_dialog->editDataSet(selected_dataset);
	if(ds) {
		selected_dataset = ds;
		emit dataSetsChanged();
	}
}

void QalculateDataSetsDialog::newDataSet() {
	if(!dataset_edit_dialog) {
		dataset_edit_dialog = new QalculateEditDataSetDialog(this);
	}
	DataSet *ds = dataset_edit_dialog->editDataSet();
	if(ds) {
		selected_dataset = ds;
		emit dataSetsChanged();
	}
}

void QalculateDataSetsDialog::dataSetDoubleClicked(TQListViewItem*i) {
	selected_dataset = dataSetItems[i];
	if(!selected_dataset)
		return;
	CHECK_IF_DATASET_STILL_THERE
	if(!dataset_edit_dialog) {
		dataset_edit_dialog = new QalculateEditDataSetDialog(this);
	}
	DataSet *ds = dataset_edit_dialog->editDataSet(selected_dataset);
	if(ds) {
		selected_dataset = ds;
		emit dataSetsChanged();
	}
}


void QalculateDataSetsDialog::dataSetSelected() {
	TQListViewItem *selected = dataSetsView->selectedItem();
	objectsView->clear();
	if(selected) {
		DataSet *ds = dataSetItems[selected];
		if(!CALCULATOR->stillHasFunction(ds)) {
			KMessageBox::error(this, i18n("Data set does not exist anymore."));
			selected_dataset = NULL;
			emit dataSetsChanged();
			return;
		}
		//remember selection
		selected_dataset = ds;

		while(objectsView->columns() > 0) {
			objectsView->removeColumn(0);
		}

		DataObjectIter it;
		DataPropertyIter pit;
		DataProperty *dp;
		DataObject *o = ds->getFirstObject(&it);
		bool b = false, b2 = false;
		TQListViewItem *i;
		while(o) {
			i = new TDEListViewItem(objectsView);
			objectItems[i] = o;
			dp = ds->getFirstProperty(&pit);
			int index = 0;
			while(dp) {
				if(!dp->isHidden() && dp->isKey()) {
					if(!b2) {
						objectsView->addColumn(dp->title().c_str());
					}
					i->setText(index, o->getPropertyDisplayString(dp).c_str());
					index++;
					if(index > 2) break;
				}
				dp = ds->getNextProperty(&pit);
			}
			b2 = true;
			if(o == selected_object) {
				objectsView->setSelected(i, true);
				b = true;
			}
			o = ds->getNextObject(&it);
		}
		if(!b) {
			TQListViewItemIterator qit(objectsView);
			if(qit.current()) {
				objectsView->setSelected(qit.current(), true);
			}
		}
		objectsView->sort();

		editDataSetButton->setEnabled(true);
		deleteDataSetButton->setEnabled(ds->isLocal());
		newObjectButton->setEnabled(true);

		TQString str, str2;

		if(!ds->description().empty()) {
			str2 = ds->description().c_str();
			str2.replace("<", "&lt;");
			str2.replace(">", "&gt;");
			str += str2;
			str += "<br><br>";
		}
		str += "<b>";
		str += i18n("Properties");
		str += "</b><br>";
		dp = ds->getFirstProperty(&pit);
		while(dp) {
			if(!dp->isHidden()) {
				if(!dp->title(false).empty()) {
					str2 = dp->title().c_str();
					str2.replace("<", "&lt;");
					str2.replace(">", "&gt;");
					str += str2;
					str += ": ";
				}
				for(size_t i = 1; i <= dp->countNames(); i++) {
					if(i > 1) str += ", ";
					str += dp->getName(i).c_str();
				}
				if(dp->isKey()) {
					str += " (";
					//indicating that the property is a data set key
					str += i18n("key");
					str += ")";
				}
				str += "<br>";
				if(!dp->description().empty()) {
					str += "<i>";
					str2 = dp->description().c_str();
					str2.replace("<", "&lt;");
					str2.replace(">", "&gt;");
					str += str2;
					str += "</i><br>";
				}
			}
			dp = ds->getNextProperty(&pit);
		}
		str += "<br><b>";
		str += i18n("Data Retrieval Function");
		str += "</b><br>";
		Argument *arg;
		Argument default_arg;
		const ExpressionName *ename = &ds->preferredName(false, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) descriptionBrowser);
		str += "<i><b>";
		str += ename->name.c_str();
		str += "</b>";
		int iargs = ds->maxargs();
		if(iargs < 0) {
			iargs = ds->minargs() + 1;
		}
		str += "(";
		if(iargs != 0) {
			for(int i2 = 1; i2 <= iargs; i2++) {
				if(i2 > ds->minargs()) {
					str += "[";
				}
				if(i2 > 1) {
					str += CALCULATOR->getComma().c_str();
					str += " ";
				}
				arg = ds->getArgumentDefinition(i2);
				if(arg && !arg->name().empty()) {
					str += arg->name().c_str();
				} else {
					str += i18n("argument");
					str += " ";
					str += TQString::number(i2);
				}
				if(i2 > ds->minargs()) {
					str += "]";
				}
			}
			if(ds->maxargs() < 0) {
				str += CALCULATOR->getComma().c_str();
				str += " ...";
			}
		}
		str += ")";
		for(size_t i2 = 1; i2 <= ds->countNames(); i2++) {
			if(&ds->getName(i2) != ename) {
				str += "<br>";
				str += ds->getName(i2).name.c_str();
			}
		}
		str += "</i>";
		str += "<br>";

		if(!ds->copyright().empty()) {
			str += "<br>";
			str2 = ds->copyright().c_str();
			str2.replace("<", "&lt;");
			str2.replace(">", "&gt;");
			str += str2;
			str += "<br>";
		}
		str.replace("\n", "<br>");
		descriptionBrowser->setText(str);

	} else {
		editDataSetButton->setEnabled(false);
		deleteDataSetButton->setEnabled(false);
		newObjectButton->setEnabled(false);
		selected_dataset = NULL;
		descriptionBrowser->clear();
	}
	objectSelected();
}

void QalculateDataSetsDialog::insertObjectData(void *data) {
	DataProperty *dp = (DataProperty*) data;
	DataSet *ds = dp->parentSet();
	if(ds && selected_object) {
		TQString str = ds->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionWidget).name.c_str();
		str += "(";
		str += selected_object->getProperty(ds->getPrimaryKeyProperty()).c_str();
		str += CALCULATOR->getComma().c_str();
		str += " ";
		str += dp->getName().c_str();
		str += ")";
		insert_text_in_expression(str);
	}
}

void QalculateDataSetsDialog::objectSelected() {

	TQListViewItem *selected = objectsView->selectedItem();
	DataObject *o = NULL;
	if(selected) o = objectItems[selected];

	if(o) {
		selected_object = o;
		editObjectButton->setEnabled(true);
		deleteObjectButton->setEnabled(true);
		DataSet *ds = o->parentSet();
		if(!ds) return;
		DataPropertyIter it;
		DataProperty *dp = ds->getFirstProperty(&it);
		TQString sval;
		TQString str;
		delete attributesGrid;
		attributesGrid = new TQGrid(3, TQt::Horizontal, attributesView->viewport());
		attributesGrid->setSpacing(spacingHint());
		attributesView->addChild(attributesGrid);
		while(dp) {
			if(!dp->isHidden()) {
				sval = o->getPropertyDisplayString(dp).c_str();
				if(!sval.isEmpty()) {
					str = "<b>"; str += dp->title().c_str(); str += ":"; str += "</b>";
					new TQLabel(str, attributesGrid);
					KLineEdit *le = new KLineEdit(sval, attributesGrid);
					le->setReadOnly(true);
					le->setFrameStyle(TQFrame::NoFrame | TQFrame::Plain);
					QalculateButtonWithData *button = new QalculateButtonWithData((void*) dp, TQIconSet(SmallIcon("edit-paste")), "", attributesGrid);
					TQObject::connect(button, TQ_SIGNAL(clickedWithData(void*)), TQ_SLOT(insertObjectData(void*)));
				}
			}
			dp = ds->getNextProperty(&it);
		}
		TQWidget *widget = new TQWidget(attributesGrid);
		widget->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Expanding);
		attributesGrid->show();
	} else {
		delete attributesGrid;
		attributesGrid = new TQGrid(3, TQt::Horizontal, attributesView->viewport());
		attributesGrid->setSpacing(spacingHint());
		attributesView->addChild(attributesGrid);
		attributesGrid->show();
		selected_object = NULL;
		editObjectButton->setEnabled(false);
		deleteObjectButton->setEnabled(false);
	}

}

void QalculateDataSetsDialog::deleteObject() {
	UPDATE_SELECTED_DATASET
	UPDATE_SELECTED_OBJECT
	selected_dataset->delObject(selected_object);
	selected_object = NULL;
	updateObjects();
}

void QalculateDataSetsDialog::updateObjects() {
	dataSetSelected();
}

void QalculateDataSetsDialog::editObject() {
	UPDATE_SELECTED_DATASET
	UPDATE_SELECTED_OBJECT
	if(!object_edit_dialog) {
		object_edit_dialog = new QalculateEditDataObjectDialog(this);
	}
	DataObject *o = object_edit_dialog->editDataObject(selected_dataset, selected_object);
	if(o) {
		selected_object = o;
		updateObjects();
	}
}

void QalculateDataSetsDialog::newObject() {
	UPDATE_SELECTED_DATASET
	if(!object_edit_dialog) {
		object_edit_dialog = new QalculateEditDataObjectDialog(this);
	}
	DataObject *o = object_edit_dialog->editDataObject(selected_dataset);
	if(o) {
		selected_object = o;
		updateObjects();
	}
}

void QalculateDataSetsDialog::objectDoubleClicked(TQListViewItem*i) {
	UPDATE_SELECTED_DATASET
	selected_object = objectItems[i];
	if(!selected_object)
		return;
	if(!object_edit_dialog) {
		object_edit_dialog = new QalculateEditDataObjectDialog(this);
	}
	DataObject *o = object_edit_dialog->editDataObject(selected_dataset, selected_object);
	if(o) {
		selected_object = o;
		updateObjects();
	}
}



#include "qalculatedatasetsdialog.moc"
