/****************************************************************************
** Dooble - The Secure Internet Web Browser
**
** Copyright (c) 2008, 2009, 2010, 2011, 2012 Alexis Megas,
** Gunther van Dooble, and the Dooble Team.
** All rights reserved.
**
** License: GPL2 only:
** 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; version 2 of the License only.
**
** 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
** or see here: http://www.gnu.org/licenses/gpl.html
**
** For the WebKit library, please see: http://webkit.org.
**
** THE CODE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY
** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS APPLICATION, EVEN IF ADVISED
** OF THE POSSIBILITY OF SUCH DAMAGE.
**
** Please report all praise, requests, bugs, and problems to the project
** team and administrators: http://sf.net/projects/dooble.
**
** You can find us listed at our project page. New team members are welcome.
** The name of the authors should not be used to endorse or promote products
** derived from Dooble without specific prior written permission.
** If you use this code for other projects, please let us know.
**
** Web sites:
**   http://sf.net/projects/dooble
**   http://dooble.sf.net
****************************************************************************/

#include <QSettings>
#include <QSqlQuery>
#include <QSqlDatabase>
#include <QFileIconProvider>

#include "dmisc.h"
#include "dooble.h"
#include "dbookmarkspopup.h"
#include "dbookmarkswindow.h"

dbookmarkspopup::dbookmarkspopup(void):QWidget()
{
  m_folderOid = -1;
  ui.setupUi(this);
#ifdef Q_WS_MAC
  setAttribute(Qt::WA_MacMetalStyle, false);
#endif
  ui.folders->setModel(dooble::s_bookmarksFolderModel);
  connect(ui.folders,
	  SIGNAL(itemSelected(const QModelIndex &)),
	  this,
	  SLOT(slotFolderSelected(const QModelIndex &)));
  connect(ui.titleLineEdit,
	  SIGNAL(returnPressed(void)),
	  this,
	  SLOT(slotTitleChanged(void)));
  connect(ui.closePushButton,
	  SIGNAL(clicked(void)),
	  this,
	  SIGNAL(closed(void)));
  connect(ui.addFolderPushButton,
	  SIGNAL(clicked(void)),
	  this,
	  SLOT(slotAddFolder(void)));
  connect(ui.descriptionTextEdit,
	  SIGNAL(textChanged(void)),
	  this,
	  SLOT(slotDescriptionChanged(void)));
  connect(ui.deleteBookmarkPushButton,
	  SIGNAL(clicked(void)),
	  this,
	  SLOT(slotDeleteBookmark(void)));
  connect(dooble::s_bookmarksFolderModel,
	  SIGNAL(dataChanged(const QModelIndex &,
			     const QModelIndex &)),
	  this,
	  SLOT(slotFolderDataChanged(const QModelIndex &,
				     const QModelIndex &)));
  slotSetIcons();
}

dbookmarkspopup::~dbookmarkspopup()
{
}

void dbookmarkspopup::populate(const QUrl &url)
{
  m_folderOid = -1;
  m_title.clear();
  m_url = url;
  ui.titleLineEdit->clear();
  ui.descriptionTextEdit->blockSignals(true);
  ui.descriptionTextEdit->clear();
  ui.descriptionTextEdit->blockSignals(false);

  /*
  ** Retrieve the bookmark's folder, title, and description.
  */

  {
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "bookmarks");

    db.setDatabaseName(dooble::s_homePath +
		       QDir::separator() + "bookmarks.db");

    if(db.open())
      {
	int temporary = dmisc::passphraseWasAuthenticated() ? 0 : 1;
	QSqlQuery query(db);

	query.prepare("SELECT title, description, folder_oid, url "
		      "FROM bookmarks WHERE temporary = ?");
	query.bindValue(0, temporary);

	if(query.exec())
	  while(query.next())
	    {
	      QUrl l_url
		(QUrl::fromEncoded
		 (dmisc::decodedString
		  (QByteArray::fromBase64
		   (query.value(3).toByteArray())),
		  QUrl::StrictMode));

	      if(l_url.toString(QUrl::StripTrailingSlash) !=
		 m_url.toString(QUrl::StripTrailingSlash))
		continue;

	      m_folderOid = query.value(2).toInt();
	      m_title =
		QString::fromUtf8
		(dmisc::decodedString
		 (QByteArray::fromBase64
		  (query.value(0).toByteArray())));

	      QString description
		(dmisc::decodedString
		 (QByteArray::fromBase64
		  (query.value(1).toByteArray())));

	      ui.titleLineEdit->setText(m_title);
	      ui.descriptionTextEdit->blockSignals(true);
	      ui.descriptionTextEdit->setPlainText(description);
	      ui.descriptionTextEdit->blockSignals(false);
	      break;
	    }
      }

    db.close();
  }

  QSqlDatabase::removeDatabase("bookmarks");
  ui.titleLineEdit->selectAll();
  ui.titleLineEdit->setFocus();

  if(dooble::s_bookmarksFolderModel->index(0, 0).isValid())
    {
      /*
      ** Recursively search for the bookmark's folder.
      ** If found, select the folder and expand its parents.
      */

      QModelIndexList list(dooble::s_bookmarksFolderModel->
			   match(dooble::s_bookmarksFolderModel->index(0, 0),
				 Qt::UserRole + 2,
				 m_folderOid,
				 1,
				 Qt::MatchRecursive));

      if(!list.isEmpty())
	{
	  ui.folders->setExpanded(list.first(), true);
	  ui.folders->selectionModel()->select
	    (list.first(), QItemSelectionModel::ClearAndSelect);
	  ui.folders->selectionModel()->setCurrentIndex
	    (list.first(), QItemSelectionModel::Current);
	}
    }
}

void dbookmarkspopup::updateBookmark(void)
{
  {
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",
						"bookmarks");

    db.setDatabaseName(dooble::s_homePath +
		       QDir::separator() + "bookmarks.db");

    if(db.open())
      {
	int temporary = dmisc::passphraseWasAuthenticated() ? 0 : 1;
	QSqlQuery query(db);

	if(query.exec(QString("SELECT url FROM bookmarks WHERE "
			      "folder_oid = %1 AND "
			      "temporary = %2").arg(m_folderOid).
		      arg(temporary)))
	  while(query.next())
	    {
	      QUrl url
		(QUrl::fromEncoded
		 (dmisc::decodedString
		  (QByteArray::fromBase64
		   (query.value(0).toByteArray())),
		  QUrl::StrictMode));

	      if(url.toString(QUrl::StripTrailingSlash) !=
		 m_url.toString(QUrl::StripTrailingSlash))
		continue;

	      QSqlQuery updateQuery(db);

	      updateQuery.exec("PRAGMA synchronous = OFF");
	      updateQuery.prepare
		("UPDATE bookmarks SET title = ?, "
		 "description = ? "
		 "WHERE url = ? AND "
		 "folder_oid = ? AND "
		 "temporary = ?");
	      updateQuery.bindValue
		(0,
		 dmisc::encodedString(m_title.toUtf8(), true).toBase64());
	      updateQuery.bindValue
		(1,
		 dmisc::encodedString(ui.descriptionTextEdit->toPlainText().
				      trimmed().toUtf8(), true).toBase64());
	      updateQuery.bindValue(2, query.value(0));
	      updateQuery.bindValue(3, m_folderOid);
	      updateQuery.bindValue(4, temporary);
	      updateQuery.exec();
	      break;
	    }
      }

    db.close();
  }

  QSqlDatabase::removeDatabase("bookmarks");
  emit changed();
}

void dbookmarkspopup::slotSetIcons(void)
{
  QPixmap pixmap;
  QSettings settings
    (dooble::s_settings.value("iconSet").toString(), QSettings::IniFormat);

  pixmap.load(settings.value("bookmarksPopup/bookmarkIcon").toString());
  ui.icon->setPixmap(pixmap.scaled(QSize(32, 32),
				   Qt::KeepAspectRatio,
				   Qt::SmoothTransformation));
  ui.closePushButton->setIcon
    (QIcon(settings.value("bookmarksPopup/closeButtonIcon").toString()));
  ui.addFolderPushButton->setIcon
    (QIcon(settings.value("bookmarksPopup/addButtonIcon").toString()));
  emit iconsChanged();
}

void dbookmarkspopup::slotAddFolder(void)
{
  QItemSelection selection(ui.folders->selectionModel()->selection());

  if(dooble::s_bookmarksWindow)
    dooble::s_bookmarksWindow->addFolder();

  if(selection.indexes().value(0).isValid())
    ui.folders->selectionModel()->select
      (selection, QItemSelectionModel::ClearAndSelect);
  else
    ui.folders->selectionModel()->select
      (dooble::s_bookmarksFolderModel->index(0, 0),
       QItemSelectionModel::ClearAndSelect);
}

void dbookmarkspopup::slotTitleChanged(void)
{
  QString title(ui.titleLineEdit->text().trimmed());

  if(title.isEmpty())
    {
      ui.titleLineEdit->setText(m_title);
      ui.titleLineEdit->selectAll();
      return;
    }
  else
    {
      m_title = title;
      ui.titleLineEdit->selectAll();
    }

  updateBookmark();
}

void dbookmarkspopup::slotDeleteBookmark(void)
{
  {
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "bookmarks");

    db.setDatabaseName(dooble::s_homePath +
		       QDir::separator() + "bookmarks.db");

    if(db.open())
      {
	int temporary = dmisc::passphraseWasAuthenticated() ? 0 : 1;
	QSqlQuery query(db);

	if(query.exec(QString("SELECT url FROM bookmarks WHERE "
			      "folder_oid = %1 AND temporary = %2").
		      arg(m_folderOid).arg(temporary)))
	  while(query.next())
	    {
	      QUrl url
		(QUrl::fromEncoded
		 (dmisc::decodedString
		  (QByteArray::fromBase64
		   (query.value(0).toByteArray())),
		  QUrl::StrictMode));

	      if(url.toString(QUrl::StripTrailingSlash) !=
		 m_url.toString(QUrl::StripTrailingSlash))
		continue;

	      QSqlQuery deleteQuery(db);

	      deleteQuery.exec("PRAGMA synchronous = OFF");
	      deleteQuery.prepare("DELETE FROM bookmarks WHERE "
				  "folder_oid = ? AND "
				  "url = ? AND "
				  "temporary = ?");
	      deleteQuery.bindValue(0, m_folderOid);
	      deleteQuery.bindValue(1, query.value(0));
	      deleteQuery.bindValue(2, temporary);
	      deleteQuery.exec();
	      break;
	    }
      }

    db.close();
  }

  QSqlDatabase::removeDatabase("bookmarks");
  emit changed();
  emit closed();
}

void dbookmarkspopup::slotFolderSelected(const QModelIndex &index)
{
  if(index.isValid())
    {
      QStandardItem *item = dooble::s_bookmarksFolderModel->itemFromIndex
	(index);

      if(item)
	{
	  m_folderOid = item->data(Qt::UserRole + 2).toInt();

	  {
	    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",
							"bookmarks");

	    db.setDatabaseName(dooble::s_homePath +
			       QDir::separator() + "bookmarks.db");

	    if(db.open())
	      {
		int temporary = dmisc::passphraseWasAuthenticated() ? 0 : 1;
		QSqlQuery query(db);

		if(query.exec(QString("SELECT url FROM bookmarks WHERE "
				      "temporary = %1").
			      arg(temporary)))
		  while(query.next())
		    {
		      QUrl url
			(QUrl::fromEncoded
			 (dmisc::decodedString
			  (QByteArray::fromBase64
			   (query.value(0).toByteArray())),
			  QUrl::StrictMode));

		      if(url.toString(QUrl::StripTrailingSlash) !=
			 m_url.toString(QUrl::StripTrailingSlash))
			continue;

		      QSqlQuery updateQuery(db);

		      updateQuery.exec("PRAGMA synchronous = OFF");
		      updateQuery.prepare
			("UPDATE bookmarks SET folder_oid = ? "
			 "WHERE url = ? AND "
			 "temporary = ?");
		      updateQuery.bindValue(0, m_folderOid);
		      updateQuery.bindValue(1, query.value(0));
		      updateQuery.bindValue(2, temporary);
		      updateQuery.exec();
		      break;
		    }
	      }

	    db.close();
	  }

	  QSqlDatabase::removeDatabase("bookmarks");
	  emit changed();
	}
    }
}

void dbookmarkspopup::slotFolderDataChanged
(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
  if(!dooble::s_bookmarksWindow)
    return;

  Q_UNUSED(bottomRight);

  QModelIndexList list(ui.folders->selectionModel()->selectedIndexes());

  if(!list.isEmpty())
    if(topLeft == list.first())
      dooble::s_bookmarksWindow->renameFolder(topLeft);
}

void dbookmarkspopup::slotDescriptionChanged(void)
{
  updateBookmark();
}
