/***************************************************************************
                          rksaveobjectchooser  -  description
                             -------------------
    begin                : Mon Nov 27 2006
    copyright            : (C) 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
    email                : thomas.friedrichsmeier@kdemail.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 "rksaveobjectchooser.h"

#include <qlineedit.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <QVBoxLayout>
#include <QPushButton>
#include <QTimer>
#include <QDialog>
#include <QDialogButtonBox>

#include <KLocalizedString>

#include "../core/robjectlist.h"
#include "../core/renvironmentobject.h"
#include "../misc/rkobjectlistview.h"

#include "../debug.h"

RKSaveObjectChooser::RKSaveObjectChooser (QWidget *parent, const QString &initial) : QWidget (parent), RObjectListener (RObjectListener::Other) {
	RK_TRACE (MISC);

	object_exists = false;
	addNotificationType (RObjectListener::ObjectRemoved);
	addNotificationType (RObjectListener::ChildAdded);
	root_object = 0;
	current_object = 0;

	QVBoxLayout *layout = new QVBoxLayout (this);
	layout->setContentsMargins (0, 0, 0, 0);

	QHBoxLayout *hlayout = new QHBoxLayout ();
	root_label = new QLabel (this);
	hlayout->addWidget (root_label);
	hlayout->addStretch ();
	root_button = new QPushButton (i18n ("Change"), this);
	connect (root_button, &QPushButton::clicked, this, &RKSaveObjectChooser::selectRootObject);
	hlayout->addWidget (root_button);
	layout->addLayout (hlayout);

	name_edit = new QLineEdit (this);
	name_edit->setText (initial);
	connect (name_edit, &QLineEdit::textChanged, this, &RKSaveObjectChooser::updateState);
	layout->addWidget (name_edit);

	overwrite_confirm = new QCheckBox (this);
	connect (overwrite_confirm, &QCheckBox::stateChanged, this, &RKSaveObjectChooser::updateState);
	layout->addWidget (overwrite_confirm);

	// initialize
	setRootObject (0);
}

RKSaveObjectChooser::~RKSaveObjectChooser () {
	RK_TRACE (MISC);

	if (current_object) stopListenForObject (current_object);
	stopListenForObject (root_object);
}

void RKSaveObjectChooser::setRootObject (RObject* new_root) {
	RK_TRACE (MISC);

	if (root_object && (new_root == root_object)) {
		return;
	}

	if (root_object) stopListenForObject (root_object);
	if (!new_root) new_root = RObjectList::getGlobalEnv ();
	else if (!new_root->isInGlobalEnv ()) new_root = RObjectList::getGlobalEnv ();
	else if (!new_root->isContainer ()) new_root = RObjectList::getGlobalEnv ();
	root_object = new_root;
	listenForObject (root_object);

	root_label->setText (i18n ("Parent object: %1", root_object->getShortName ()));

	updateState ();
}

void RKSaveObjectChooser::selectRootObject () {
	RK_TRACE (MISC);

	// TODO: not very pretty, yet
	QDialog *dialog = new QDialog (this);
	dialog->setWindowTitle (i18n ("Select parent object"));
	dialog->setModal (true);
	QVBoxLayout *layout = new QVBoxLayout (dialog);

	RKObjectListView* list_view = new RKObjectListView (false, dialog);
	list_view->setSelectionMode (QAbstractItemView::SingleSelection);
	list_view->initialize ();
	list_view->setObjectCurrent (root_object);
	connect (list_view, &QAbstractItemView::doubleClicked, dialog, &QDialog::accept);
	layout->addWidget (list_view);

	QDialogButtonBox *buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, dialog);
	connect (buttons->button (QDialogButtonBox::Ok), &QPushButton::clicked, dialog, &QDialog::accept);
	connect (buttons->button (QDialogButtonBox::Cancel), &QPushButton::clicked, dialog, &QDialog::reject);
	layout->addWidget (buttons);

	dialog->exec ();

	if (dialog->result () == QDialog::Accepted) {
		RObject::ObjectList sel = list_view->selectedObjects ();
		if (sel.isEmpty ()) setRootObject (0);
		else {
			RK_ASSERT (sel.size () == 1);
			setRootObject (sel[0]);
		}
	}

	delete dialog;
}

void RKSaveObjectChooser::objectRemoved (RObject* removed) {
	RK_TRACE (MISC);

	if (removed == root_object) {
		setRootObject (0);
	} else if (removed == current_object) {
		stopListenForObject (removed);
		current_full_name.clear ();	// hack to achieve proper emit of change signal
		QTimer::singleShot (0, this, SLOT (updateState()));
	} else {
		RK_ASSERT (false);
	}
}

void RKSaveObjectChooser::childAdded (int, RObject* parent) {
	RK_TRACE (MISC);

	if (parent == root_object) {
		updateState ();
	} else {
		// unusual, but ok
		RK_ASSERT (parent == current_object);
	}
}

void RKSaveObjectChooser::setBaseName (const QString &name) {
	RK_TRACE (MISC);

	name_edit->setText (name);
	updateState ();
}

bool RKSaveObjectChooser::isOk () const {
	RK_TRACE (MISC);

	if (name_edit->text ().isEmpty ()) return false;
	return ((!object_exists) || overwrite_confirm->isChecked ());
}

void RKSaveObjectChooser::updateState () {
	RK_TRACE (MISC);
	RK_ASSERT (root_object && root_object->isContainer ());

	QString new_name = static_cast<RContainerObject*> (root_object)->validizeName (name_edit->text (), false);
	if (current_object) stopListenForObject (current_object);
	current_object = root_object->findObject (new_name);
	new_name = root_object->makeChildName (new_name);	// make it the full name
	if (current_object) {
		object_exists = true;
		overwrite_confirm->setText (i18n ("Overwrite? (The given object name already exists)"));
		overwrite_confirm->setEnabled (true);
		listenForObject (current_object);
	} else {
		object_exists = false;
		overwrite_confirm->setText (i18n ("Overwrite?"));
		overwrite_confirm->setEnabled (false);
		overwrite_confirm->setChecked (false);
	}

	if ((new_name != current_full_name) || (sender () == overwrite_confirm)) {
		current_full_name = new_name;
		emit (changed (isOk ()));
	}
}

void RKSaveObjectChooser::setBackgroundColor (const QColor &color) {
	RK_TRACE (MISC);

	QPalette palette = name_edit->palette ();
	palette.setColor (name_edit->backgroundRole (), color);
	name_edit->setPalette (palette);
}

QString RKSaveObjectChooser::currentBaseName () const {
	return name_edit->text ();
}

