/*
 * Copyright (C) 2004 Stephan Möres <Erdling@gmx.net>
 */

#include "plugin_katesnippets.h"

#include <kaction.h>
#include <klocale.h>
#include <kstandarddirs.h>

class PluginView : public KXMLGUIClient
{
  friend class KatePluginKateSnippets;

  public:
    Kate::MainWindow *win;
};

extern "C"
{
  void* init_katesnippetsplugin()
  {
    KGlobal::locale()->insertCatalogue("katekatesnippets");
    return new KatePluginFactory;
  }
}

KatePluginFactory::KatePluginFactory()
{
  s_instance = new KInstance( "kate" );
}

KatePluginFactory::~KatePluginFactory()
{
  delete s_instance;
}

QObject* KatePluginFactory::createObject( QObject* parent, const char* name, const char*, const QStringList & )
{
  return new KatePluginKateSnippets( parent, name );
}

KInstance* KatePluginFactory::s_instance = 0L;

KatePluginKateSnippets::KatePluginKateSnippets( QObject* parent, const char* name )
    : Kate::Plugin ( (Kate::Application*)parent, name )
{
	tvaSnippets = NULL;
//	dockSnippets = NULL;
	widgetSnippets = NULL;

    lSnippets.setAutoDelete( TRUE ); // the list owns the objects

	config = new KConfig("katesnippetspluginrc");

	// should be here, but is in addView, as the snippetswidget
	// gets filled up here ...
//	readConfig();

}

KatePluginKateSnippets::~KatePluginKateSnippets()
{
	writeConfig();
}

void KatePluginKateSnippets::addView(Kate::MainWindow *win)
{
    // TODO: doesn't this have to be deleted?
    PluginView *view = new PluginView ();


	//<to map the different snippet-actions to one slot>
/*
	snippetActionMapper = new QSignalMapper( this );
	connect(
		snippetActionMapper, SIGNAL( mapped( int ) ),
		this, SLOT( slot_InsertSnippet( int ) )
	);
*/
	//</to map the different snippet-actions to one slot>



//	pActionCollection = new KActionCollection(this, "Hello");
/*
     (void) new KAction ( i18n("Insert Hello World"), 0, this,
                      SLOT( slotInsertHello() ), view->actionCollection(),
                      "edit_insert_katesnippets" );
*/
    view->setInstance (new KInstance("kate"));
    view->setXMLFile("plugins/katesnippets/plugin_katesnippets.rc");
    win->guiFactory()->addClient (view);
    view->win = win;

	m_views.append (view);

	//<create dock-widget : snippets>
	KIconLoader *loader = KGlobal::iconLoader();
	QPixmap icon_snippets;
	icon_snippets = loader->loadIcon("contents", KIcon::Desktop);

	Kate::ToolViewManager *tool_view_manager = win->toolViewManager();

//	dockSnippets = tool_view_manager->addToolView(KDockWidget::DockLeft, "dockSnippets", icon_snippets, i18n("Snippets"));

    widgetSnippets = new CWidgetSnippets((QWidget*)0, "snippetswidget");
	
    tvaSnippets = tool_view_manager->addToolView(
		KDockWidget::DockLeft,
		widgetSnippets,
		icon_snippets, 
		"dockSnippets",
		i18n("Snippets"),
		i18n("Snippets")
	);

//	widgetSnippets->show();
	//</create dock-widget : snippets>


	//<make connections>
	connect (
		widgetSnippets->lvSnippets, SIGNAL( selectionChanged(QListViewItem *) ),
        this, SLOT( slot_lvSnippetsSelectionChanged(QListViewItem *) )
    );
	connect (
		widgetSnippets->lvSnippets, SIGNAL( doubleClicked (QListViewItem *) ),
        this, SLOT( slot_lvSnippetsClicked(QListViewItem  *) )
    );
	connect (
		widgetSnippets->lvSnippets, SIGNAL( itemRenamed(QListViewItem *, int, const QString &) ),
        this, SLOT( slot_lvSnippetsItemRenamed(QListViewItem *, int, const QString &) )
    );

	connect (
		widgetSnippets->btnNew, SIGNAL( clicked () ),
        this, SLOT( slot_btnNewClicked() )
    );
	connect (
		widgetSnippets->btnSave, SIGNAL( clicked () ),
        this, SLOT( slot_btnSaveClicked() )
    );
	connect (
		widgetSnippets->btnDelete, SIGNAL( clicked () ),
        this, SLOT( slot_btnDeleteClicked() )
    );
	//</make connections>

	// should be in the constructor, but is here
	// as the snippetswidget gets filled up here ...
	readConfig();

}
void KatePluginKateSnippets::removeView(Kate::MainWindow *win)
{
  for (uint z=0; z < m_views.count(); z++)
    if (m_views.at(z)->win == win)
    {
      PluginView *view = m_views.at(z);
      m_views.remove (view);
      win->guiFactory()->removeClient (view);
      delete view;
    }

    if (tvaSnippets != NULL)
    {
        win->toolViewManager()->removeToolView(tvaSnippets);
//        delete dockSnippets;
        tvaSnippets = NULL;
		widgetSnippets = NULL;
	}
}

void KatePluginKateSnippets::slotInsertHello()
{
  Kate::View *kv = application()->activeMainWindow()->viewManager()->activeView();

  if (kv)
    kv->insertText ("Hello World");
}

void KatePluginKateSnippets::slot_lvSnippetsSelectionChanged(QListViewItem  * item) {
	CSnippet *snippet;
	if ( (snippet = findSnippetByListViewItem(item))!= NULL ) {
		widgetSnippets->teSnippetText->setText(snippet->getValue());
	}

}
/*!
    \fn KatePluginKateSnippets::void slot_lbSnippetsClicked (QListViewItem * item)
	Special meaning of <mark/> and <cursor/> ...
 */
void KatePluginKateSnippets::slot_lvSnippetsClicked (QListViewItem  * item)
{
	Kate::View *kv = application()->activeMainWindow()->viewManager()->activeView();
	CSnippet *snippet;

	if (kv) {
		if ( (snippet = findSnippetByListViewItem(item))!= NULL ) {
			QString sText = snippet->getValue();
			QString sSelection = "";

			if ( kv->getDoc()->hasSelection() ) {
				sSelection = kv->getDoc()->selection();
				// clear selection
				kv->keyDelete();
			}

			sText.replace( QRegExp("<mark/>"), sSelection );
			sText.replace( QRegExp("<date/>"), QDate::currentDate().toString(Qt::LocalDate) );
			sText.replace( QRegExp("<time/>"), QTime::currentTime().toString(Qt::LocalDate) );
			kv->insertText ( sText );
		}
		kv->setFocus();
	}
}
void KatePluginKateSnippets::slot_lvSnippetsItemRenamed(QListViewItem *lvi,int col, const QString& text) {
	CSnippet *snippet;
	if ( (snippet = findSnippetByListViewItem(lvi)) != NULL ) {
		snippet->setKey( text );
		writeConfig();
	}
}

void KatePluginKateSnippets::slot_btnNewClicked() {
	QString sKey = "New Snippet";
	QString sValue = "";

	QListViewItem *lvi = widgetSnippets->insertItem(sKey, true);
	lSnippets.append( new CSnippet(sKey, sValue, lvi, this, snippetActionMapper) );
}
void KatePluginKateSnippets::slot_btnSaveClicked() {
	CSnippet *snippet;
	QListViewItem *lvi = widgetSnippets->lvSnippets->selectedItem();
	if ( (snippet = findSnippetByListViewItem(lvi)) != NULL ) {
		snippet->setValue(widgetSnippets->teSnippetText->text() );
		writeConfig();
	}
 }
void KatePluginKateSnippets::slot_btnDeleteClicked() {
	CSnippet *snippet;
	QListViewItem *lvi = widgetSnippets->lvSnippets->selectedItem();


	if ( (snippet = findSnippetByListViewItem(lvi)) != NULL ) {
		widgetSnippets->lvSnippets->takeItem(lvi);
		lSnippets.remove(snippet);
	}
}


/*!
    \fn KatePluginKateSnippets::readConfig()
 */
void KatePluginKateSnippets::readConfig()
{
	QString sKey, sValue;
	QListViewItem *lvi;

    config->setGroup("Snippets");

	int iNrOfSnippets = config->readEntry("NumberOfSnippets", "0").toInt() ;
	for (int i=0; i < iNrOfSnippets; i++)
	{
		QStringList slFields;
		slFields = config->readListEntry ( QString::number(i) );

		sKey   = slFields[0];
		sValue = slFields[1];

		lvi = widgetSnippets->insertItem(sKey, false);

		lSnippets.append( new CSnippet(sKey, sValue, lvi, this, snippetActionMapper) );
	}

	// <defaults>
	if ( iNrOfSnippets == 0 ) {
		sKey	= "DEBUG variable";
		sValue = "## < DEBUG >\nout \"<pre>\\$<mark/> : \\\"$<mark/>\\\"\\n</pre>\"\n## </DEBUG >\n";
		lvi = widgetSnippets->insertItem(sKey, false);
		lSnippets.append( new CSnippet(sKey, sValue, lvi, this, snippetActionMapper) );

		sKey	= "proc-header";
		sValue	= "## [created : <date/>, <time/>]\n## Description:\n## ============\n## The function \"<mark/>\" ...\n##\n##\n##\n##\n## Input:\n## ======\n##\n##\n##\nproc <mark/> {args} {\n\n	## add your code here\n\n	return \"\"\n}\n";
		lvi = widgetSnippets->insertItem(sKey, false);
		lSnippets.append( new CSnippet(sKey, sValue, lvi, this, snippetActionMapper) );
	}
	// </defaults>

}
void KatePluginKateSnippets::writeConfig()
{
	config->setGroup("Snippets");

    int iNrOfSnippets = lSnippets.count();

    config->writeEntry("NumberOfSnippets", iNrOfSnippets );

    int i=0;

	CSnippet *snippet;
    for ( snippet = lSnippets.first(); snippet; snippet = lSnippets.next() ) {
		QStringList slFields;
		slFields.append( snippet->getKey() );
		slFields.append( snippet->getValue() );

		config->writeEntry ( QString::number(i), slFields, ',' );
        i++;
    }
	// sync to disc ...
	config->sync();
}

/*!
    \fn KatePluginKateSnippets::findSnippetByListViewItem(QListViewItem *item)
 */
CSnippet* KatePluginKateSnippets::findSnippetByListViewItem(QListViewItem *item)
{
	CSnippet *snippet = NULL;
    for ( snippet = lSnippets.first(); snippet; snippet = lSnippets.next() ) {
		if ( snippet->getListViewItem() == item)
			break;
	}
	return snippet;
}

/*
PluginView* KatePluginKateSnippets::getFirstView() {
	Kate::MainWindow *win = application()->activeMainWindow();

	PluginView *view = NULL;

	for (uint z=0; z < m_views.count(); z++)
        if (m_views.at(z)->win == win)
        {
			break;
		}
	return view;
}
*/

#include "plugin_katesnippets.moc"
